summaryrefslogtreecommitdiffstats
path: root/ansible_collections/cisco/aci/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
commit7fec0b69a082aaeec72fee0612766aa42f6b1b4d (patch)
treeefb569b86ca4da888717f5433e757145fa322e08 /ansible_collections/cisco/aci/tests
parentReleasing progress-linux version 7.7.0+dfsg-3~progress7.99u1. (diff)
downloadansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.tar.xz
ansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.zip
Merging upstream version 9.4.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/cisco/aci/tests')
-rw-r--r--ansible_collections/cisco/aci/tests/integration/inventory.networking5
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml61
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml82
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml334
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml532
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml280
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml120
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml100
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml202
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml140
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml155
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml187
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.crt14
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml79
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml8
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml81
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml252
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml10
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml10
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml131
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml101
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml107
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml161
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml258
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml346
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml84
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml179
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml305
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml158
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml264
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml245
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml396
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml238
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml218
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml229
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/pki/rsa_ansible.key15
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml231
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml776
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml154
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml164
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml143
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml34
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml44
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml160
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml147
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml231
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml292
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml143
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml255
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml233
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml174
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml130
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml270
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml19
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml184
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml364
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml4
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml45
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml149
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml175
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml174
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml184
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml150
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml157
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml152
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml146
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml159
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml136
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml110
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml37
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml27
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml6
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml21
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.json1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.xml1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml60
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml27
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml29
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml197
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml145
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/tasks/main.yml236
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml13
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml18
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml221
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml307
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml84
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/filter_plugins/generate_ips.py28
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.crt14
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin_invalid.key3
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/openssh_rsa.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_ansible.key15
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.crt14
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml653
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml81
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml146
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml214
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml440
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml4
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/aliases0
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml233
154 files changed, 14376 insertions, 1041 deletions
diff --git a/ansible_collections/cisco/aci/tests/integration/inventory.networking b/ansible_collections/cisco/aci/tests/integration/inventory.networking
index 16e3d1ee1..357f58758 100644
--- a/ansible_collections/cisco/aci/tests/integration/inventory.networking
+++ b/ansible_collections/cisco/aci/tests/integration/inventory.networking
@@ -3,11 +3,12 @@ cn-dmz-apic-m1-02-v42 ansible_host=173.36.219.68 aci_hostname=173.36.219.68
cn-dmz-apic-m1-03-v52 ansible_host=173.36.219.69 aci_hostname=173.36.219.69
cn-dmz-apic-m1-04-v60 ansible_host=173.36.219.70 aci_hostname=173.36.219.70
cn-dmz-apic-m1-07-v32 ansible_host=173.36.219.73 aci_hostname=173.36.219.73
-aws_cloud ansible_host=52.52.20.121 aci_hostname=52.52.20.121 aci_password="sJ94G92#8dq2hx*K4qh" cloud_type=aws region=us-east-1 region_2=us-west-1 availability_zone=us-west-1a
-azure_cloud ansible_host=20.245.236.136 aci_hostname=20.245.236.136 aci_password="sJ94G92#8dq2hx*K4qh" cloud_type=azure region=westus region_2=westus2 vnet_gateway=true
+aws_cloud ansible_host=52.52.20.121 aci_hostname=52.52.20.121 cloud_type=aws region=us-east-1 region_2=us-west-1 availability_zone=us-west-1a
+azure_cloud ansible_host=20.245.236.136 aci_hostname=20.245.236.136 cloud_type=azure region=westus region_2=westus2 vnet_gateway=true
[aci:vars]
aci_username=ansible_github_ci
aci_password="sJ94G92#8dq2hx*K4qh"
+ansible_network_os=cisco.aci.aci
ansible_connection=local
ansible_python_interpreter=/usr/bin/python3.9
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml
index 56de63830..52f3ed0fb 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml
@@ -8,23 +8,14 @@
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: Remove any pre-existing user
- cisco.aci.aci_aaa_user: &user_absent
- 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") }}'
- aaa_user: ansible
+- name: Uninstall dateutil for error checking
+ ansible.builtin.pip: &dateutil
+ name: python-dateutil
state: absent
-
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
# ADD USER
-- name: Add user (check_mode)
+- name: Add user without dateutil installed (error)
cisco.aci.aci_aaa_user: &user_present
host: '{{ aci_hostname }}'
username: '{{ aci_username }}'
@@ -42,6 +33,36 @@
first_name: Test
last_name: User
phone: 1-234-555-678
+ ignore_errors: true
+ register: err_no_python_dateutil
+
+- name: Verify add user
+ ansible.builtin.assert:
+ that:
+ - err_no_python_dateutil.msg == "dateutil required for this module"
+
+- name: Install dateutil
+ ansible.builtin.pip:
+ <<: *dateutil
+ state: present
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+# CLEAN ENVIRONMENT
+- name: Remove any pre-existing user
+ cisco.aci.aci_aaa_user: &user_absent
+ 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") }}'
+ aaa_user: ansible
+ state: absent
+
+# ADD USER
+- name: Add user (check_mode)
+ cisco.aci.aci_aaa_user: *user_present
check_mode: true
register: cm_add_user
@@ -49,7 +70,8 @@
- name: Add user (normal mode)
cisco.aci.aci_aaa_user:
<<: *user_present
- aaa_password: 12!Ab:cD!34
+ # changed password because password strength check is triggered on the 6.0(2h) version, thus failing testcase
+ aaa_password: khsaubf@3ijsdn!!2#%nbsh
register: nm_add_user
- name: Add user again (check mode)
@@ -72,7 +94,6 @@
- nm_add_user_again is not changed
- nm_add_user_again.current.0.aaaUser.attributes.descr == 'Ansible test user'
-
# MODIFY USER
- name: Modify user (check_mode)
cisco.aci.aci_aaa_user: &user_changed
@@ -92,6 +113,13 @@
check_mode: true
register: cm_modify_user
+- name: Error wrong expiration (error)
+ cisco.aci.aci_aaa_user:
+ <<: *user_changed
+ expiration: wrong_expiration
+ ignore_errors: true
+ register: err_modify_user_expiration
+
- name: Modify user (normal mode)
cisco.aci.aci_aaa_user: *user_changed
register: nm_modify_user
@@ -109,6 +137,7 @@
assert:
that:
- cm_modify_user is changed
+ - err_modify_user_expiration.msg == "Failed to parse date format 'wrong_expiration', Unknown string format{{":"}} wrong_expiration"
- nm_modify_user is changed
- nm_modify_user.current.0.aaaUser.attributes.descr == 'Ansible test user for integration tests'
- cm_modify_user_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml
index 9d300e4d7..3140816e0 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml
@@ -300,13 +300,13 @@
state: present
- name: Remove user ansible_test
- aci_aaa_user:
- <<: *aci_info
- aaa_user: ansible_test
- state: absent
+ cisco.aci.aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible_test
+ state: absent
- name: Add user ansible_test
- aci_aaa_user:
+ cisco.aci.aci_aaa_user:
<<: *aci_info
aaa_user: ansible_test
aaa_password: ansible_5351
@@ -315,7 +315,7 @@
state: present
- name: Add user certificate
- aci_aaa_user_certificate:
+ cisco.aci.aci_aaa_user_certificate:
<<: *aci_info
aaa_user: ansible_test
name: test
@@ -323,10 +323,8 @@
state: present
- name: Query test certificate
- aci_aaa_user_certificate:
- host: "{{ aci_hostname }}"
- username: "{{ aci_username }}"
- validate_certs: '{{ aci_validate_certs | default(false) }}'
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
certificate_name: admin
private_key: '{{ role_path }}/pki/admin.key'
aaa_user: ansible_test
@@ -334,13 +332,75 @@
state: query
register: query_test
+- name: Query test certificate with a private key file and no certificate name
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ private_key: '{{ role_path }}/pki/admin.key'
+ aaa_user: ansible_test
+ name: test
+ state: query
+ register: query_test_pk_file
+
+- name: Query test certificate with a non existent key
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ private_key: '{{ role_path }}/pki/non_existent.key'
+ aaa_user: ansible_test
+ name: test
+ state: query
+ register: query_test_non_existent_key
+ ignore_errors: true
+
+- name: Query test certificate with private key content and no certificate name present
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ private_key: |
+ -----BEGIN PRIVATE KEY-----
+ MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKIRv+2sbbewm0mj
+ D+6/tpoUymzYIdFsN+gu02teIr/lZi8ipEB514pyhoaerstzboPteWvniLuwq4KQ
+ VTEHgoln7J8EaHCnECViGA61pVx8RkJ99cmCkepspROw3I96zBcm58oXs6+Q/BnD
+ /OWET5sBvR9oTv9GNRVJ1rvSMAEJAgMBAAECgYByu3QO0qF9h7X3JEu0Ld4cKBnB
+ giQ2uJC/et7KxIJ/LOvw9GopBthyt27KwG1ntBkJpkTuAaQHkyNns7vLkNB0S0IR
+ +owVFEcKYq9VCHTaiQU8TDp24gN+yPTrpRuH8YhDVq5SfVdVuTMgHVQdj4ya4VlF
+ Gj+a7+ipxtGiLsVGrQJBAM7p0Fm0xmzi+tBOASUAcVrPLcteFIaTBFwfq16dm/ON
+ 00Khla8Et5kMBttTbqbukl8mxFjBEEBlhQqb6EdQQ0sCQQDIhHx1a9diG7y/4DQA
+ 4KvR3FCYwP8PBORlSamegzCo+P1OzxiEo0amX7yQMA5UyiP/kUsZrme2JBZgna8S
+ p4R7AkEAr7rMhSOPUnMD6V4WgsJ5g1Jp5kqkzBaYoVUUSms5RASz4+cwJVCwTX91
+ Y1jcpVIBZmaaY3a0wrx13ajEAa0dOQJBAIpjnb4wqpsEh7VpmJqOdSdGxb1XXfFQ
+ sA0T1OQYqQnFppWwqrxIL+d9pZdiA1ITnNqyvUFBNETqDSOrUHwwb2cCQGArE+vu
+ ffPUWQ0j+fiK+covFG8NL7H+26NSGB5+Xsn9uwOGLj7K/YT6CbBtr9hJiuWjM1Al
+ 0V4ltlTuu2mTMaw=
+ -----END PRIVATE KEY-----
+ aaa_user: ansible_test
+ name: test
+ state: query
+ register: query_test_pk_content
+
- name: Verify query_test
assert:
that:
- query_test is not changed
+ - query_test_pk_file is not changed
+ - '"Provided private key ******** does not appear to be a private key or provided file does not exist." in query_test_non_existent_key.msg'
+ - query_test_pk_content is not changed
+
+# Cleanup environment
+- name: Remove test certificate
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ aaa_user: ansible_test
+ name: test
+ state: absent
- name: Remove user to clean environment for next test on ci
- aci_aaa_user:
+ cisco.aci.aci_aaa_user:
<<: *aci_info
aaa_user: ansible_test
state: absent
+
+- name: Remove test certificate
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ aaa_user: '{{ aci_username }}'
+ name: admin
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml
new file mode 100644
index 000000000..e2d00e525
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group/tasks/main.yml
@@ -0,0 +1,334 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all span source groups ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span source groups ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all span destination groups ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span destination groups ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Execute tasks only for non-cloud sites ( clean before )
+ when:
+ - query_cloud.current == []
+ block:
+ - name: Query all access span filter groups ( clean before )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+ - name: Clean access span filter groups ( clean before )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item.spanFilterGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+ - name: Add a access span filter groups ( clean before )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item }}"
+ state: present
+ loop:
+ - span_filter_group_1
+ - span_filter_group_2
+
+- name: Add access span destination group type epg ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+- name: Add access span destination group type access interface port ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_2
+ description: test span access interface port
+ access_interface:
+ pod: 1
+ node: 101
+ path: eth1/1
+ mtu: 1500
+ state: present
+
+- name: Add access span destination group type access interface direct port channel ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_3
+ description: test span access interface port channel
+ access_interface:
+ pod: 1
+ node: 101
+ path: test-PolGrp
+ state: present
+
+# TEST CREATE SOURCE GROUPS
+
+- name: Add access span source group 1 ( checkmode )
+ cisco.aci.aci_access_span_src_group: &span_src_1
+ <<: *aci_info
+ source_group: span_src_1
+ destination_group: span_dest_1
+ filter_group: span_filter_group_1
+ state: present
+ check_mode: true
+ register: cm_span_src_1
+
+- name: Add access span source group 1
+ cisco.aci.aci_access_span_src_group:
+ <<: *span_src_1
+ register: nm_span_src_1
+
+- name: Add access span source group 1 again
+ cisco.aci.aci_access_span_src_group:
+ <<: *span_src_1
+ register: nm_span_src_1_again
+
+- name: Verify add access span source group 1
+ ansible.builtin.assert:
+ that:
+ - cm_span_src_1 is changed
+ - cm_span_src_1.previous == []
+ - cm_span_src_1.current == []
+ - cm_span_src_1.proposed.spanSrcGrp.attributes.name == "span_src_1"
+ - cm_span_src_1.proposed.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_1"
+ - cm_span_src_1.proposed.spanSrcGrp.children.1.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_span_src_1 is changed
+ - nm_span_src_1.previous == []
+ - nm_span_src_1.current.0.spanSrcGrp.attributes.name == "span_src_1"
+ - nm_span_src_1.current.0.spanSrcGrp.attributes.descr == ""
+ - nm_span_src_1.current.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_span_src_1.current.0.spanSrcGrp.children.1.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_span_src_1.current.0.spanSrcGrp.children.0.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_span_src_1_again is not changed
+ - nm_span_src_1_again.previous.0.spanSrcGrp.attributes.name == "span_src_1"
+ - nm_span_src_1_again.previous.0.spanSrcGrp.attributes.descr == ""
+ - nm_span_src_1_again.previous.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_span_src_1_again.previous.0.spanSrcGrp.children.1.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_span_src_1_again.previous.0.spanSrcGrp.children.0.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_span_src_1_again.current.0.spanSrcGrp.attributes.name == "span_src_1"
+ - nm_span_src_1_again.current.0.spanSrcGrp.attributes.descr == ""
+ - nm_span_src_1_again.current.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_span_src_1_again.current.0.spanSrcGrp.children.1.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_span_src_1_again.current.0.spanSrcGrp.children.0.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+
+- name: Change access span source group 1
+ cisco.aci.aci_access_span_src_group: &change_span_src_1
+ <<: *span_src_1
+ destination_group: span_dest_2
+ filter_group: span_filter_group_2
+ description: "changed description"
+ admin_state: false
+ register: nm_changed_span_src_1
+
+- name: Change access span source group 1 again
+ cisco.aci.aci_access_span_src_group:
+ <<: *change_span_src_1
+ register: nm_changed_span_src_1_again
+
+- name: Change access span source group 1 remove filter group
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: span_src_1
+ destination_group: span_dest_2
+ register: nm_changed_span_src_1_remove_filter_group
+
+- name: Verify changed access span source group 1
+ ansible.builtin.assert:
+ that:
+ - nm_changed_span_src_1 is changed
+ - nm_changed_span_src_1.previous.0.spanSrcGrp.attributes.descr == ""
+ - nm_changed_span_src_1.previous.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_changed_span_src_1.previous.0.spanSrcGrp.children.1.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_changed_span_src_1.previous.0.spanSrcGrp.children.0.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_changed_span_src_1.current.0.spanSrcGrp.attributes.descr == "changed description"
+ - nm_changed_span_src_1.current.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_1.current.0.spanSrcGrp.children.1.spanSpanLbl.attributes.name == "span_dest_2"
+ - nm_changed_span_src_1.current.0.spanSrcGrp.children.0.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_2"
+ - nm_changed_span_src_1_again is not changed
+ - nm_changed_span_src_1_again.previous.0.spanSrcGrp.attributes.descr == "changed description"
+ - nm_changed_span_src_1_again.previous.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_1_again.previous.0.spanSrcGrp.children.1.spanSpanLbl.attributes.name == "span_dest_2"
+ - nm_changed_span_src_1_again.previous.0.spanSrcGrp.children.0.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_2"
+ - nm_changed_span_src_1_again.current.0.spanSrcGrp.attributes.descr == "changed description"
+ - nm_changed_span_src_1_again.current.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_1_again.current.0.spanSrcGrp.children.1.spanSpanLbl.attributes.name == "span_dest_2"
+ - nm_changed_span_src_1_again.current.0.spanSrcGrp.children.0.spanRsSrcGrpToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_2"
+ - nm_changed_span_src_1_remove_filter_group is changed
+ - nm_changed_span_src_1_remove_filter_group.current.0.spanSrcGrp.children | length == 1
+ - nm_changed_span_src_1_remove_filter_group.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_2"
+
+- name: Add access span source group 2 with admin_state to false
+ cisco.aci.aci_access_span_src_group:
+ <<: *change_span_src_1
+ source_group: span_src_2
+ destination_group: span_dest_2
+ admin_state: false
+ register: nm_changed_span_src_2_admin_state_false
+
+- name: Add another access span source group 3 with admin_state to true
+ cisco.aci.aci_access_span_src_group:
+ <<: *change_span_src_1
+ source_group: span_src_3
+ destination_group: span_dest_3
+ admin_state: true
+ register: nm_changed_span_src_3_admin_state_true
+
+- name: Verify admin_state sets for access span source group 2 and 3
+ ansible.builtin.assert:
+ that:
+ - nm_changed_span_src_2_admin_state_false is changed
+ - nm_changed_span_src_2_admin_state_false.current.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_3_admin_state_true is changed
+ - nm_changed_span_src_3_admin_state_true.current.0.spanSrcGrp.attributes.adminSt == "enabled"
+
+# TEST QUERY SOURCE GROUPS
+
+- name: Query span source group span_src_1
+ cisco.aci.aci_access_span_src_group:
+ <<: *change_span_src_1
+ state: query
+ register: query_one
+
+- name: Query all span source groups
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying access span destination groups
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanSrcGrp.attributes.name == "span_src_1"
+ - query_all is not changed
+ - query_all.current | length >= 3
+
+# TEST REMOVAL SOURCE GROUPS
+
+- name: Remove span source group ( checkmode )
+ cisco.aci.aci_access_span_src_group: &remove_span_src_1
+ <<: *change_span_src_1
+ state: absent
+ check_mode: true
+ register: cm_remove_span_src_1
+
+- name: Remove span source group
+ cisco.aci.aci_access_span_src_group:
+ <<: *remove_span_src_1
+ register: nm_remove_span_src_1
+
+- name: Remove span source group again
+ cisco.aci.aci_access_span_src_group:
+ <<: *remove_span_src_1
+ register: nm_remove_span_src_1_again
+
+- name: Verify remove access span destination groups
+ ansible.builtin.assert:
+ that:
+ - cm_remove_span_src_1 is changed
+ - cm_remove_span_src_1.current | length == 1
+ - cm_remove_span_src_1.previous | length == 1
+ - cm_remove_span_src_1.proposed == {}
+ - nm_remove_span_src_1 is changed
+ - nm_remove_span_src_1.current == []
+ - nm_remove_span_src_1.previous | length == 1
+ - nm_remove_span_src_1_again is not changed
+ - nm_remove_span_src_1_again.current == []
+ - nm_remove_span_src_1_again.previous == []
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all span source groups ( clean after )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span source groups ( clean after )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all span destination groups ( clean after )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span destination groups ( clean after )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Execute tasks only for non-cloud sites ( clean after )
+ when:
+ - query_cloud.current == []
+ block:
+ - name: Query all access span filter groups ( clean after )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+ - name: Clean access span filter groups ( clean after )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item.spanFilterGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml
new file mode 100644
index 000000000..a0fe48f08
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src/tasks/main.yml
@@ -0,0 +1,532 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all span source groups ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span source groups ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all span destination groups ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span destination groups ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Execute tasks only for non-cloud sites ( clean before )
+ when:
+ - query_cloud.current == []
+ block:
+ - name: Query all access span filter groups ( clean before )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+ - name: Clean access span filter groups ( clean before )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item.spanFilterGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+ - name: Add a access span filter groups ( clean before )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item }}"
+ state: present
+ loop:
+ - span_filter_group_1
+ - span_filter_group_2
+
+- name: Add access span destination group type epg ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+- name: Add access span source group 1 ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item }}"
+ destination_group: span_dest_1
+ state: present
+ loop:
+ - span_src_group_1
+ - span_src_group_2
+ - span_src_group_3
+
+# TEST CREATE SOURCE
+
+- name: Add access span source 1 ( checkmode )
+ cisco.aci.aci_access_span_src_group_src: &span_src_1
+ <<: *aci_info
+ source_group: span_src_group_1
+ filter_group: span_filter_group_1
+ source: span_src_1
+ state: present
+ check_mode: true
+ register: cm_span_src_1
+
+- name: Add access span source 1
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *span_src_1
+ register: nm_span_src_1
+
+- name: Add access span source 1 again
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *span_src_1
+ register: nm_span_src_1_again
+
+- name: Verify add access span source group 1
+ ansible.builtin.assert:
+ that:
+ - cm_span_src_1 is changed
+ - cm_span_src_1.previous == []
+ - cm_span_src_1.current == []
+ - cm_span_src_1.proposed.spanSrc.attributes.name == "span_src_1"
+ - cm_span_src_1.proposed.spanSrc.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1"
+ - cm_span_src_1.proposed.spanSrc.children.0.spanRsSrcToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_span_src_1 is changed
+ - nm_span_src_1.previous == []
+ - nm_span_src_1.current.0.spanSrc.attributes.name == "span_src_1"
+ - nm_span_src_1.current.0.spanSrc.attributes.descr == ""
+ - nm_span_src_1.current.0.spanSrc.attributes.dir == "both"
+ - nm_span_src_1.current.0.spanSrc.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1"
+ - nm_span_src_1.current.0.spanSrc.children.0.spanRsSrcToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_span_src_1_again is not changed
+ - nm_span_src_1_again.previous.0.spanSrc.attributes.name == "span_src_1"
+ - nm_span_src_1_again.previous.0.spanSrc.attributes.descr == ""
+ - nm_span_src_1_again.previous.0.spanSrc.attributes.dir == "both"
+ - nm_span_src_1_again.previous.0.spanSrc.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1"
+ - nm_span_src_1_again.previous.0.spanSrc.children.0.spanRsSrcToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_span_src_1_again.current.0.spanSrc.attributes.name == "span_src_1"
+ - nm_span_src_1_again.current.0.spanSrc.attributes.descr == ""
+ - nm_span_src_1_again.current.0.spanSrc.attributes.dir == "both"
+ - nm_span_src_1_again.current.0.spanSrc.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1"
+ - nm_span_src_1_again.current.0.spanSrc.children.0.spanRsSrcToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+
+- name: Change access span source group 1
+ cisco.aci.aci_access_span_src_group_src: &change_span_src_1
+ <<: *span_src_1
+ source: span_src_1
+ filter_group: span_filter_group_2
+ description: "changed description"
+ direction: both
+ register: nm_changed_span_src_1
+
+- name: Change access span source group 1 direction incoming
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *change_span_src_1
+ direction: incoming
+ register: nm_changed_span_src_1_incoming
+
+- name: Change access span source group 1 direction outgoing
+ cisco.aci.aci_access_span_src_group_src: &change_span_src_1_again
+ <<: *change_span_src_1
+ direction: outgoing
+ register: nm_changed_span_src_1_outgoing
+
+- name: Change access span source group 1 again
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *change_span_src_1_again
+ register: nm_changed_span_src_1_again
+
+- name: Verify changed access span source group 1
+ ansible.builtin.assert:
+ that:
+ - nm_changed_span_src_1 is changed
+ - nm_changed_span_src_1.previous.0.spanSrc.attributes.name == "span_src_1"
+ - nm_changed_span_src_1.previous.0.spanSrc.attributes.descr == ""
+ - nm_changed_span_src_1.previous.0.spanSrc.attributes.dir == "both"
+ - nm_changed_span_src_1.previous.0.spanSrc.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1"
+ - nm_changed_span_src_1.previous.0.spanSrc.children.0.spanRsSrcToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_1"
+ - nm_changed_span_src_1.current.0.spanSrc.attributes.name == "span_src_1"
+ - nm_changed_span_src_1.current.0.spanSrc.attributes.descr == "changed description"
+ - nm_changed_span_src_1.current.0.spanSrc.attributes.dir == "both"
+ - nm_changed_span_src_1.current.0.spanSrc.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1"
+ - nm_changed_span_src_1.current.0.spanSrc.children.0.spanRsSrcToFilterGrp.attributes.tDn == "uni/infra/filtergrp-span_filter_group_2"
+ - nm_changed_span_src_1_incoming.current.0.spanSrc.attributes.dir == "in"
+ - nm_changed_span_src_1_outgoing.current.0.spanSrc.attributes.dir == "out"
+ - nm_changed_span_src_1_again is not changed
+
+- name: Add access span source 2 of epg type
+ cisco.aci.aci_access_span_src_group_src: &span_src_epg
+ <<: *aci_info
+ source_group: span_src_group_2
+ epg:
+ tenant: tenant1
+ ap: ap1
+ epg: epg1
+ source: span_src_2
+ state: present
+ register: nm_span_src_2
+
+- name: Change access span source 2 of epg type
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *span_src_epg
+ epg:
+ tenant: tenant1
+ ap: ap1
+ epg: epg2
+ register: nm_changed_span_src_2
+
+- name: Change access span source 2 of epg type to none type
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_2
+ source: span_src_2
+ state: present
+ register: nm_changed_span_src_2_type_none
+
+- name: Add access span source 3 of routed_outside type
+ cisco.aci.aci_access_span_src_group_src: &span_src_routed_outside
+ <<: *aci_info
+ source_group: span_src_group_3
+ routed_outside:
+ tenant: tenant1
+ l3out: l3out1
+ encap: 1089
+ source: span_src_3
+ state: present
+ register: nm_span_src_3
+
+- name: Add access span source 3 of routed_outside type without l3out
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *span_src_routed_outside
+ routed_outside:
+ tenant: tenant1
+ encap: 1089
+ state: present
+ register: nm_changed_span_src_3_no_l3out
+
+- name: Add access span source 3 of routed_outside type without encap
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *span_src_routed_outside
+ routed_outside:
+ tenant: tenant1
+ l3out: l3out1
+ state: present
+ register: nm_changed_span_src_3_no_encap
+
+- name: Add access span source 3 of routed_outside type without tenant
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *span_src_routed_outside
+ routed_outside:
+ l3out: l3out1
+ encap: 1089
+ state: present
+ register: nm_changed_span_src_3_no_tenant
+
+- name: Change access span source 3 of routed_outside type
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *span_src_routed_outside
+ routed_outside:
+ tenant: tenant1
+ l3out: l3out2
+ encap: 1090
+ register: nm_changed_span_src_3
+
+- name: Change access span source 3 of routed_outside type to epg type
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_3
+ source: span_src_3
+ epg:
+ tenant: tenant1
+ ap: ap1
+ epg: epg3
+ state: present
+ register: nm_changed_span_src_3_type_epg
+
+- name: Verify changed access span source types group 2 and 3
+ ansible.builtin.assert:
+ that:
+ - nm_span_src_2 is changed
+ - nm_span_src_2.current.0.spanSrc.attributes.name == "span_src_2"
+ - nm_span_src_2.current.0.spanSrc.children.0.spanRsSrcToEpg.attributes.tDn == "uni/tn-tenant1/ap-ap1/epg-epg1"
+ - nm_changed_span_src_2 is changed
+ - nm_changed_span_src_2.current.0.spanSrc.attributes.name == "span_src_2"
+ - nm_changed_span_src_2.current.0.spanSrc.children.0.spanRsSrcToEpg.attributes.tDn == "uni/tn-tenant1/ap-ap1/epg-epg2"
+ - nm_changed_span_src_2_type_none is changed
+ - nm_changed_span_src_2_type_none.previous.0.spanSrc.children.0.spanRsSrcToEpg.attributes.tDn == "uni/tn-tenant1/ap-ap1/epg-epg2"
+ - '"children" not in nm_changed_span_src_2_type_none.current.0.spanSrc'
+ - nm_span_src_3 is changed
+ - nm_span_src_3.current.0.spanSrc.attributes.name == "span_src_3"
+ - nm_span_src_3.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.tDn == "uni/tn-tenant1/out-l3out1"
+ - nm_span_src_3.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.encap == "vlan-1089"
+ - nm_changed_span_src_3 is changed
+ - nm_changed_span_src_3.current.0.spanSrc.attributes.name == "span_src_3"
+ - nm_changed_span_src_3.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.tDn == "uni/tn-tenant1/out-l3out2"
+ - nm_changed_span_src_3.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.encap == "vlan-1090"
+ - nm_changed_span_src_3_type_epg is changed
+ - nm_changed_span_src_3_type_epg.current.0.spanSrc.attributes.name == "span_src_3"
+ - nm_changed_span_src_3_type_epg.current.0.spanSrc.children.0.spanRsSrcToEpg.attributes.tDn == "uni/tn-tenant1/ap-ap1/epg-epg3"
+ - nm_changed_span_src_3_no_l3out is changed
+ - nm_changed_span_src_3_no_l3out.current.0.spanSrc.attributes.name == "span_src_3"
+ - nm_changed_span_src_3_no_l3out.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.encap == "vlan-1089"
+ - nm_changed_span_src_3_no_l3out.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.tDn == ""
+ - nm_changed_span_src_3_no_tenant is changed
+ - nm_changed_span_src_3_no_tenant.current.0.spanSrc.attributes.name == "span_src_3"
+ - nm_changed_span_src_3_no_tenant.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.encap == "vlan-1089"
+ - nm_changed_span_src_3_no_tenant.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.tDn == ""
+ - nm_changed_span_src_3_no_encap is changed
+ - nm_changed_span_src_3_no_encap.current.0.spanSrc.attributes.name == "span_src_3"
+ - nm_changed_span_src_3_no_encap.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.encap == "unknown"
+ - nm_changed_span_src_3_no_encap.current.0.spanSrc.children.0.spanRsSrcToL3extOut.attributes.tDn == "uni/tn-tenant1/out-l3out1"
+
+- name: Change access span source 2 drop_packets true
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_2
+ source: span_src_2
+ drop_packets: true
+ state: present
+ register: nm_changed_span_src_2_type_drop_packets_true
+
+- name: Change access span source 2 drop_packets false
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_2
+ source: span_src_2
+ drop_packets: false
+ state: present
+ register: nm_changed_span_src_2_type_drop_packets_false
+
+- name: Verify changed access span source group 1 drop packets
+ ansible.builtin.assert:
+ that:
+ - nm_changed_span_src_2_type_drop_packets_true is changed
+ - nm_changed_span_src_2_type_drop_packets_true.current.0.spanSrc.attributes.name == "span_src_2"
+ - nm_changed_span_src_2_type_drop_packets_true.current.0.spanSrc.attributes.spanOnDrop == "yes"
+ - nm_changed_span_src_2_type_drop_packets_false is changed
+ - nm_changed_span_src_2_type_drop_packets_false.current.0.spanSrc.attributes.name == "span_src_2"
+ - nm_changed_span_src_2_type_drop_packets_false.current.0.spanSrc.attributes.spanOnDrop == "no"
+
+# TEST QUERY SOURCE
+
+- name: Query span source group span_src_1
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source: span_src_1
+ state: query
+ register: query_one
+
+- name: Query all span source groups
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying access span sources
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanSrc.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1"
+ - query_all is not changed
+ - query_all.current | length >= 3
+
+# TEST ERRORS SOURCE
+
+- name: Add access span source group 4
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: span_src_group_4
+ destination_group: span_dest_1
+ filter_group: span_filter_group_1
+ state: present
+
+- name: Add access span source 4 with epg and routed_outside ( mutually exclusive error )
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ epg:
+ tenant: tenant1
+ ap: ap1
+ epg: epg3
+ routed_outside:
+ tenant: tenant1
+ l3out: l3out2
+ encap: 1090
+ source: span_src_4
+ state: present
+ ignore_errors: true
+ register: err_mutually_exclusive_epg_routed_outside
+
+- name: Add access span source 4 with filter_group and drop_packets( drop_packets true error )
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ filter_group: span_filter_group_1
+ source: span_src_4
+ drop_packets: true
+ ignore_errors: true
+ register: err_filter_group_drop_packets
+
+- name: Add access span source 4 with epg and drop_packets ( drop_packets true error )
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ source: span_src_4
+ epg:
+ tenant: tenant1
+ ap: ap1
+ epg: epg3
+ drop_packets: true
+ ignore_errors: true
+ register: err_epg_drop_packets
+
+- name: Add access span source 4 with routed_outside and drop_packets ( drop_packets true error )
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ source: span_src_4
+ routed_outside:
+ tenant: tenant1
+ l3out: l3out2
+ encap: 1090
+ drop_packets: true
+ ignore_errors: true
+ register: err_routed_outside_drop_packets
+
+- name: Add access span source 4 with drop_packets true ( parent filter group config error )
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ source: span_src_4
+ drop_packets: true
+ state: present
+ ignore_errors: true
+ register: err_parent_filter_and_drop_packets
+
+- name: Verify errors on incorrect input
+ ansible.builtin.assert:
+ that:
+ - err_mutually_exclusive_epg_routed_outside.msg == "parameters are mutually exclusive{{':'}} epg|routed_outside"
+ - err_filter_group_drop_packets.msg == "Setting 'drop_packets' to 'true' is not allowed when 'filter_group' is configured on the source."
+ - err_epg_drop_packets.msg == "Setting 'drop_packets' to 'true' is not allowed when 'epg' is configured on the source."
+ - err_routed_outside_drop_packets.msg == "Setting 'drop_packets' to 'true' is not allowed when 'routed_outside' is configured on the source."
+ - err_parent_filter_and_drop_packets.msg == "APIC Error 105{{':'}} Span on drop not supported for the configuration"
+
+# TEST REMOVAL SOURCE
+
+- name: Remove span source group ( checkmode )
+ cisco.aci.aci_access_span_src_group_src: &remove_span_src_1
+ <<: *change_span_src_1
+ state: absent
+ check_mode: true
+ register: cm_remove_span_src_1
+
+- name: Remove span source group
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *remove_span_src_1
+ register: nm_remove_span_src_1
+
+- name: Remove span source group again
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *remove_span_src_1
+ register: nm_remove_span_src_1_again
+
+- name: Verify remove access span destination groups
+ ansible.builtin.assert:
+ that:
+ - cm_remove_span_src_1 is changed
+ - cm_remove_span_src_1.current | length == 1
+ - cm_remove_span_src_1.previous | length == 1
+ - cm_remove_span_src_1.proposed == {}
+ - nm_remove_span_src_1 is changed
+ - nm_remove_span_src_1.current == []
+ - nm_remove_span_src_1.previous | length == 1
+ - nm_remove_span_src_1_again is not changed
+ - nm_remove_span_src_1_again.current == []
+ - nm_remove_span_src_1_again.previous == []
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all span source groups ( clean after )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span source groups ( clean after )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all span destination groups ( clean after )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span destination groups ( clean after )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Execute tasks only for non-cloud sites ( clean after )
+ when:
+ - query_cloud.current == []
+ block:
+ - name: Query all access span filter groups ( clean after )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+ - name: Clean access span filter groups ( clean after )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item.spanFilterGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml
new file mode 100644
index 000000000..f370b1323
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_src_group_src_path/tasks/main.yml
@@ -0,0 +1,280 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all span source groups ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span source groups ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all span destination groups ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span destination groups ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Add access span destination group type epg ( clean before )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+- name: Add access span source group 1 ( clean before )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: span_src_group_1
+ destination_group: span_dest_1
+ state: present
+
+- name: Add access span source group source 1 ( clean before )
+ cisco.aci.aci_access_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ state: present
+
+# TEST CREATE SOURCE PATHS
+
+- name: Add access span source path 1 of type port ( checkmode )
+ cisco.aci.aci_access_span_src_group_src_path: &span_src_path_1
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ nodes:
+ - 101
+ path_ep: eth1/1
+ state: present
+ check_mode: true
+ register: cm_span_src_path_1
+
+- name: Add access span source 1 of type port
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *span_src_path_1
+ register: nm_span_src_path_1
+
+- name: Add access span source 1 of type port again
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *span_src_path_1
+ register: nm_span_src_path_1_again
+
+- name: Add access span source path 2 of type Direct Port Channel
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ nodes:
+ - 101
+ path_ep: test_pc_pol_group
+ state: present
+ register: nm_span_src_path_2
+
+- name: Add access span source path 3 of type VPC component PC
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ nodes:
+ - 101
+ path_ep: test_vpc_pol_group
+ state: present
+ register: nm_span_src_path_3
+
+- name: Add access span source path 4 of type Virtual Port Channel
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ nodes:
+ - 101
+ - 104
+ path_ep: test_vpc_pol_group
+ state: present
+ register: nm_span_src_path_4
+
+- name: Verify add access span source group 1 of type port
+ ansible.builtin.assert:
+ that:
+ - cm_span_src_path_1 is changed
+ - cm_span_src_path_1.previous == []
+ - cm_span_src_path_1.current == []
+ - cm_span_src_path_1.proposed.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - cm_span_src_path_1.proposed.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_span_src_path_1 is changed
+ - nm_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_span_src_path_1.previous == []
+ - nm_span_src_path_1_again is not changed
+ - nm_span_src_path_1_again.previous.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_span_src_path_1_again.previous.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_span_src_path_1_again.current.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_span_src_path_1_again.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_span_src_path_2 is changed
+ - nm_span_src_path_2.previous == []
+ - nm_span_src_path_2.current.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[test_pc_pol_group]]"
+ - nm_span_src_path_2.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[test_pc_pol_group]"
+ - nm_span_src_path_3 is changed
+ - nm_span_src_path_3.previous == []
+ - nm_span_src_path_3.current.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[test_vpc_pol_group]]"
+ - nm_span_src_path_3.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[test_vpc_pol_group]"
+ - nm_span_src_path_4 is changed
+ - nm_span_src_path_4.previous == []
+ - nm_span_src_path_4.current.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/protpaths-101-104/pathep-[test_vpc_pol_group]]"
+ - nm_span_src_path_4.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/protpaths-101-104/pathep-[test_vpc_pol_group]"
+
+# TEST QUERY SOURCE PATHS
+
+- name: Query span source group path span_src_path_1
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *span_src_path_1
+ state: query
+ register: query_one
+
+- name: Query all span source group paths
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying access span sources
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - query_one.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - query_all is not changed
+ - query_all.current | length >= 4
+
+# TEST ERRORS SOURCE PATHS
+
+- name: Add access span source path 5 of type Virtual Port Channel
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ nodes:
+ - 101
+ - 102
+ - 104
+ path_ep: test_vpc_pol_group
+ state: present
+ ignore_errors: true
+ register: err_too_many_nodes
+
+- name: Verify errors on incorrect input
+ ansible.builtin.assert:
+ that:
+ - err_too_many_nodes.msg == "3 nodes have been provided, where a maximum of 2 nodes is allowed."
+
+# TEST REMOVAL SOURCE PATHS
+
+- name: Remove span source group ( checkmode )
+ cisco.aci.aci_access_span_src_group_src_path: &remove_span_src_path_1
+ <<: *span_src_path_1
+ state: absent
+ check_mode: true
+ register: cm_remove_span_src_path_1
+
+- name: Remove span source group
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *remove_span_src_path_1
+ register: nm_remove_span_src_path_1
+
+- name: Remove span source group again
+ cisco.aci.aci_access_span_src_group_src_path:
+ <<: *remove_span_src_path_1
+ register: nm_remove_span_src_path_1_again
+
+- name: Verify remove access span destination groups
+ ansible.builtin.assert:
+ that:
+ - cm_remove_span_src_path_1 is changed
+ - cm_remove_span_src_path_1.current | length == 1
+ - cm_remove_span_src_path_1.previous | length == 1
+ - cm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - cm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - cm_remove_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - cm_remove_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - cm_remove_span_src_path_1.proposed == {}
+ - nm_remove_span_src_path_1 is changed
+ - nm_remove_span_src_path_1.current == []
+ - nm_remove_span_src_path_1.previous | length == 1
+ - nm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.dn == "uni/infra/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_remove_span_src_path_1_again is not changed
+ - nm_remove_span_src_path_1_again.current == []
+ - nm_remove_span_src_path_1_again.previous == []
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all span source groups ( clean after )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span source groups ( clean after )
+ cisco.aci.aci_access_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all span destination groups ( clean after )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span destination groups ( clean after )
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml
index a69d255ff..2a4f6f23e 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml
@@ -8,6 +8,18 @@
msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+- name: Set vars
+ ansible.builtin.set_fact:
+ aci_info: &aci_info
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_password }}'
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug # required debug due to asserts done on url which are only present in debug mode
+
+
- name: Verify Cloud and Non-Cloud Sites in use.
include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
@@ -17,55 +29,43 @@
# CLEAN ENVIRONMENT
- name: Remove AEP to domain binding
cisco.aci.aci_aep_to_domain: &binding_absent
- 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") }}'
+ <<: *aci_info
aep: test_aep
domain: phys_dom
domain_type: phys
state: absent
+ - name: Delete AEP
+ cisco.aci.aci_aep:
+ <<: *aci_info
+ aep: test_aep
+ description: Test AEP
+ state: absent
+
- name: Create AEP
cisco.aci.aci_aep:
- 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") }}'
+ <<: *aci_info
aep: test_aep
description: Test AEP
state: present
- name: Create physical domain
cisco.aci.aci_domain:
- 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") }}'
+ <<: *aci_info
domain: phys_dom
domain_type: phys
state: present
+ - name: Ensure vmm domain exist
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: api/mo/uni/vmmp-VMware/dom-anstest.json
+ content: {"vmmDomP": {"attributes": {}}}
# ADD BINDING
- name: Add AEP to domain binding (check_mode)
cisco.aci.aci_aep_to_domain: &binding_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: '{{ aci_output_level | default("info") }}'
+ <<: *aci_info
aep: test_aep
domain: phys_dom
domain_type: phys
@@ -104,17 +104,67 @@
- cm_add_binding_again is not changed
- nm_add_binding_again is not changed
+ - name: Add AEP to domain type not vmm with vm provider (error)
+ cisco.aci.aci_aep_to_domain:
+ <<: *aci_info
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ vm_provider: vmware
+ ignore_errors: true
+ register: err_not_vmm_with_vm_provider
+
+ - name: Add AEP to domain with type fc
+ cisco.aci.aci_aep_to_domain:
+ <<: *aci_info
+ aep: test_aep
+ domain: fc_dom
+ domain_type: fc
+ register: nm_fc_type
+
+ - name: Add AEP to domain with type l2dom
+ cisco.aci.aci_aep_to_domain:
+ <<: *aci_info
+ aep: test_aep
+ domain: l2dom_dom
+ domain_type: l2dom
+ register: nm_l2dom_type
+
+ - name: Add AEP to domain with type l3dom
+ cisco.aci.aci_aep_to_domain:
+ <<: *aci_info
+ aep: test_aep
+ domain: l3dom_dom
+ domain_type: l3dom
+ register: nm_l3dom_type
+
+ - name: Add AEP to domain with type vmm
+ cisco.aci.aci_aep_to_domain:
+ <<: *aci_info
+ aep: test_aep
+ domain: anstest
+ domain_type: vmm
+ vm_provider: vmware
+ register: nm_vmm_type
+
+ - name: Verify bindings with domain types
+ assert:
+ that:
+ - err_not_vmm_with_vm_provider is not changed
+ - err_not_vmm_with_vm_provider.msg == "Domain type 'phys' cannot have a 'vm_provider'"
+ - nm_fc_type is changed
+ - nm_fc_type.current.0.infraRsDomP.attributes.tDn == "uni/fc-fc_dom"
+ - nm_l2dom_type is changed
+ - nm_l2dom_type.current.0.infraRsDomP.attributes.tDn == "uni/l2dom-l2dom_dom"
+ - nm_l3dom_type is changed
+ - nm_l3dom_type.current.0.infraRsDomP.attributes.tDn == "uni/l3dom-l3dom_dom"
+ - nm_vmm_type is changed
+ - nm_vmm_type.current.0.infraRsDomP.attributes.tDn == "uni/vmmp-VMware/dom-anstest"
# QUERY ALL BINDINGS
- name: Query all AEP to domain bindings (check_mode)
cisco.aci.aci_aep_to_domain: &binding_query
- 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") }}'
+ <<: *aci_info
state: query
check_mode: true
register: cm_query_all_bindings
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml
index 10f00990c..4bc8e26c4 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml
@@ -8,6 +8,24 @@
msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- name: Query system information
+ cisco.aci.aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
- name: Verify Cloud and Non-Cloud Sites in use.
include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
@@ -16,17 +34,17 @@
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
- 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
+ <<: *aci_info
tenant: ansible_test
register: tenant_present
+ - name: Query system information
+ cisco.aci.aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
- name: ensure bd exists for tests to kick off
cisco.aci.aci_bd: &aci_bd_present
<<: *aci_tenant_present
@@ -60,7 +78,7 @@
<<: *aci_subnet_present
register: create_subnet
- - name: create new subnet - creation works
+ - name: create new subnet - creation works (with no ip_data_plane_learning - APIC version < 5.0)
cisco.aci.aci_bd_subnet: &aci_subnet2_present
<<: *aci_subnet2_absent
state: present
@@ -69,6 +87,19 @@
route_profile: default
route_profile_l3_out: default
register: create_subnet2
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: create new subnet - creation works (with ip_data_plane_learning - APIC version >= 5.0)
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet2_present
+ state: present
+ descr: Ansible Test
+ scope: [private, shared]
+ route_profile: default
+ route_profile_l3_out: default
+ ip_data_plane_learning: disabled
+ register: create_subnet2_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
- name: create subnet again - idempotency works
cisco.aci.aci_bd_subnet:
@@ -96,7 +127,7 @@
register: create_incomplete_data
ignore_errors: true
- - name: asserts for subnet creation tasks
+ - name: assert for subnet creation tasks
assert:
that:
- create_check_mode is changed
@@ -106,11 +137,6 @@
- create_subnet is changed
- create_subnet.current.0.fvSubnet.attributes.annotation == 'orchestrator:ansible'
- create_subnet.previous == []
- - create_subnet2 is changed
- - create_subnet2.sent == create_subnet2.proposed
- - create_subnet2.sent.fvSubnet.attributes.scope == "private,shared"
- - create_subnet2.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnL3extOutName == 'default'
- - create_subnet2.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnRtctrlProfileName == 'default'
- create_idempotency is not changed
- create_idempotency.previous != []
- modify_subnet is changed
@@ -123,6 +149,28 @@
- create_incomplete_data is failed
- 'create_incomplete_data.msg == "state is present but all of the following are missing: bd"'
+ - name: assert for subnet for task with version < 5
+ assert:
+ that:
+ - create_subnet2 is changed
+ - create_subnet2.sent == create_subnet2.proposed
+ - create_subnet2.sent.fvSubnet.attributes.scope == "private,shared"
+ - create_subnet2.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnL3extOutName == 'default'
+ - create_subnet2.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnRtctrlProfileName == 'default'
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: assert for subnet ip_data_learning for task with version >=5
+ assert:
+ that:
+ - create_subnet.current.0.fvSubnet.attributes.ipDPLearning == 'enabled'
+ - create_subnet2_5 is changed
+ - create_subnet2_5.current.0.fvSubnet.attributes.ipDPLearning == 'disabled'
+ - create_subnet2_5.sent == create_subnet2_5.proposed
+ - create_subnet2_5.sent.fvSubnet.attributes.scope == "private,shared"
+ - create_subnet2_5.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnL3extOutName == 'default'
+ - create_subnet2_5.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnRtctrlProfileName == 'default'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
- name: get all subnets
cisco.aci.aci_bd_subnet: &aci_query
<<: *aci_tenant_present
@@ -203,6 +251,28 @@
- '"query-target-filter=eq(fvSubnet.ip,\"10.100.100.1/24\")" in get_subnets_gateway.filter_string'
- '"class/fvSubnet.json" in get_subnets_gateway.url'
+ - name: error handling for ipv4 subnet with wrong mask
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_bd_present
+ gateway: 10.100.100.1
+ mask: 33
+ ignore_errors: true
+ register: error_mask_ipv4
+
+ - name: error handling for ipv6 subnet with wrong mask
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_bd_present
+ gateway: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
+ mask: 129
+ ignore_errors: true
+ register: error_mask_ipv6
+
+ - name: asserts for mask error handling
+ assert:
+ that:
+ - error_mask_ipv4.msg == "Valid Subnet Masks are 0 to 32 for IPv4 Addresses"
+ - error_mask_ipv6.msg == "Valid Subnet Masks are 0 to 128 for IPv6 Addresses"
+
- name: delete subnet - check mode works
cisco.aci.aci_bd_subnet:
<<: *aci_subnet_absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml
new file mode 100644
index 000000000..7d1313fb2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_to_l3out/tasks/main.yml
@@ -0,0 +1,202 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ cisco.aci.aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+
+- 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: Create tenant
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_tenant_absent
+ state: present
+
+ - name: Create vrf
+ cisco.aci.aci_vrf: &aci_vrf_present
+ <<: *aci_tenant_present
+ vrf: anstest
+
+ - name: Create first L3out
+ cisco.aci.aci_l3out: &aci_l3_out_present
+ <<: *aci_vrf_present
+ l3out: ansible_l3out
+ domain: ansible_dom
+ state: present
+
+ - name: Create second L3out
+ cisco.aci.aci_l3out: &aci_l3_out_present_2
+ <<: *aci_vrf_present
+ l3out: ansible_l3out_2
+ domain: ansible_dom
+ state: present
+
+ - name: Create first bd
+ cisco.aci.aci_bd: &aci_bd_present
+ <<: *aci_tenant_present
+ bd: anstest
+
+ - name: Create second bd
+ cisco.aci.aci_bd: &aci_bd_present_2
+ <<: *aci_tenant_present
+ bd: anstest_2
+
+ - name: Ensure first binding bd_to_l3out does not exist
+ cisco.aci.aci_bd_to_l3out: &aci_bd_to_l3out_absent
+ <<: *aci_tenant_present
+ bd: anstest
+ l3out: ansible_l3out
+ state: absent
+
+ - name: Ensure second binding bd_to_l3out does not exist
+ cisco.aci.aci_bd_to_l3out: &aci_bd_to_l3out_absent_2
+ <<: *aci_tenant_present
+ bd: anstest_2
+ l3out: ansible_l3out_2
+ state: absent
+
+ - name: bind bd to L3out - first binding (check_mode)
+ cisco.aci.aci_bd_to_l3out: &aci_bd_to_l3out_present
+ <<: *aci_bd_to_l3out_absent
+ state: present
+ check_mode: true
+ register: cm_bd_to_l3out
+
+ - name: bind bd to L3out - first binding (normal_mode)
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_bd_to_l3out_present
+ register: nm_bd_to_l3out
+
+ - name: bind bd to L3out again - testing idempotency
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_bd_to_l3out_present
+ register: bd_to_l3out_idempotency
+
+ - name: bind bd to L3out - second binding
+ cisco.aci.aci_bd_to_l3out: &aci_bd_to_l3out_present_2
+ <<: *aci_bd_to_l3out_absent_2
+ state: present
+ register: nm_bd_to_l3out_2
+
+ - name: asserts for creation tasks
+ assert:
+ that:
+ - cm_bd_to_l3out is changed
+ - cm_bd_to_l3out.previous == []
+ - cm_bd_to_l3out.current == []
+ - nm_bd_to_l3out is changed
+ - nm_bd_to_l3out.current.0.fvRsBDToOut.attributes.dn == "uni/tn-ansible_test/BD-anstest/rsBDToOut-ansible_l3out"
+ - nm_bd_to_l3out.current.0.fvRsBDToOut.attributes.tnL3extOutName == "ansible_l3out"
+ - bd_to_l3out_idempotency is not changed
+ - nm_bd_to_l3out_2 is changed
+ - nm_bd_to_l3out_2.current.0.fvRsBDToOut.attributes.dn == "uni/tn-ansible_test/BD-anstest_2/rsBDToOut-ansible_l3out_2"
+ - nm_bd_to_l3out_2.current.0.fvRsBDToOut.attributes.tnL3extOutName == "ansible_l3out_2"
+
+ - name: Query all bds bound to l3outs
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_tenant_present
+ state: query
+ register: query_all_bd_to_l3out
+
+ - name: Query first bd bound to first l3out
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_bd_to_l3out_present
+ state: query
+ register: query_first_bd_to_l3out
+
+ - name: asserts query tasks
+ assert:
+ that:
+ - query_all_bd_to_l3out is not changed
+ - '"fvRsBDToOut" in query_all_bd_to_l3out.filter_string'
+ - query_all_bd_to_l3out.current.0.fvTenant.children | length >= 2
+ - query_all_bd_to_l3out.current.0.fvTenant.children.0.fvBD.attributes.name == "anstest_2"
+ - query_all_bd_to_l3out.current.0.fvTenant.children.0.fvBD.children.0.fvRsBDToOut.attributes.tRn == "out-ansible_l3out_2"
+ - query_all_bd_to_l3out.current.0.fvTenant.children.1.fvBD.attributes.name == "anstest"
+ - query_all_bd_to_l3out.current.0.fvTenant.children.1.fvBD.children.0.fvRsBDToOut.attributes.tRn == "out-ansible_l3out"
+ - query_first_bd_to_l3out is not changed
+ - '"tn-ansible_test/BD-anstest/rsBDToOut-ansible_l3out.json" in query_first_bd_to_l3out.url'
+
+ - name: unbind bd to l3out - first binding (check_mode)
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_bd_to_l3out_present
+ state: absent
+ check_mode: true
+ register: cm_unbind_bd_to_l3out
+
+ - name: unbind bd to l3out - first binding (normal_mode)
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_bd_to_l3out_present
+ state: absent
+ register: nm_unbind_bd_to_l3out
+
+ - name: unbind bd to l3out again - testing idempotency
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_bd_to_l3out_present
+ state: absent
+ register: unbind_bd_to_l3out_idempotency
+
+ - name: unbind bd to l3out - second binding
+ cisco.aci.aci_bd_to_l3out:
+ <<: *aci_bd_to_l3out_present_2
+ state: absent
+ register: nm_unbind_bd_to_l3out_2
+
+ - name: asserts for deletion tasks
+ assert:
+ that:
+ - cm_unbind_bd_to_l3out is changed
+ - cm_unbind_bd_to_l3out.proposed == {}
+ - nm_unbind_bd_to_l3out is changed
+ - nm_unbind_bd_to_l3out.previous != []
+ - nm_unbind_bd_to_l3out.method == "DELETE"
+ - unbind_bd_to_l3out_idempotency is not changed
+ - unbind_bd_to_l3out_idempotency.previous == []
+ - nm_unbind_bd_to_l3out_2 is changed
+ - nm_unbind_bd_to_l3out_2.previous != []
+ - nm_unbind_bd_to_l3out_2.method == "DELETE"
+
+ - name: delete bd - cleanup before ending tests
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ state: absent
+
+ - name: delete l3out - cleanup before ending tests
+ cisco.aci.aci_l3out:
+ <<: *aci_l3_out_present
+ state: absent
+
+ - name: delete vrf - cleanup before ending tests
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ state: absent
+
+ - name: delete tenant - cleanup before ending tests
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml
new file mode 100644
index 000000000..d0eae2666
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_best_path_policy/tasks/main.yml
@@ -0,0 +1,140 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a BGP best path policy (check_mode)
+ aci_bgp_best_path_policy: &aci_bgp_best_path_policy_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ bgp_best_path_policy: ansible_bgp_best_path_policy_1
+ best_path_control: enable
+ description: BGP best path policy 1 for ansible_tenant tenant
+ state: present
+ check_mode: true
+ register: cm_add_bgp_best_path_policy
+
+ - name: Add a BGP best path policy (normal_mode)
+ aci_bgp_best_path_policy:
+ <<: *aci_bgp_best_path_policy_present
+ register: nm_add_bgp_best_path_policy
+
+ - name: Add the first BGP best path policy again - testing idempotency
+ aci_bgp_best_path_policy:
+ <<: *aci_bgp_best_path_policy_present
+ register: nm_add_bgp_best_path_policy_idempotency
+
+ - name: Add a second BGP best path policy (normal_mode)
+ aci_bgp_best_path_policy:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bgp_best_path_policy: ansible_bgp_best_path_policy_2
+ best_path_control: disable
+ description: BGP best path policy 2 for ansible_tenant tenant
+ state: present
+ register: nm_add_bgp_best_path_policy_2
+
+ - name: Asserts for BGP best path policys creation tasks
+ assert:
+ that:
+ - cm_add_bgp_best_path_policy is changed
+ - cm_add_bgp_best_path_policy.previous == []
+ - cm_add_bgp_best_path_policy.current == []
+ - nm_add_bgp_best_path_policy is changed
+ - nm_add_bgp_best_path_policy.current.0.bgpBestPathCtrlPol.attributes.name == "ansible_bgp_best_path_policy_1"
+ - nm_add_bgp_best_path_policy.current.0.bgpBestPathCtrlPol.attributes.ctrl == "asPathMultipathRelax"
+ - nm_add_bgp_best_path_policy_idempotency is not changed
+ - nm_add_bgp_best_path_policy_2 is changed
+ - nm_add_bgp_best_path_policy_2.previous == []
+ - nm_add_bgp_best_path_policy_2.current.0.bgpBestPathCtrlPol.attributes.name == "ansible_bgp_best_path_policy_2"
+ - nm_add_bgp_best_path_policy_2.current.0.bgpBestPathCtrlPol.attributes.ctrl == ""
+
+ - name: Query all BGP best path policies
+ aci_bgp_best_path_policy:
+ <<: *aci_info
+ state: query
+ register: query_all_bgp_best_path_policy
+
+ - name: Query ansible_bgp_best_path_policy_1
+ aci_bgp_best_path_policy:
+ <<: *aci_bgp_best_path_policy_present
+ state: query
+ register: query_ansible_bgp_best_path_policy_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_bgp_best_path_policy is not changed
+ - query_all_bgp_best_path_policy.current|length >= 2
+ - query_ansible_bgp_best_path_policy_1 is not changed
+ - query_ansible_bgp_best_path_policy_1.current.0.bgpBestPathCtrlPol.attributes.name == "ansible_bgp_best_path_policy_1"
+ - query_ansible_bgp_best_path_policy_1.current.0.bgpBestPathCtrlPol.attributes.ctrl == "asPathMultipathRelax"
+
+ - name: Remove BGP best path policy (check_mode)
+ aci_bgp_best_path_policy: &bgp_best_path_policy_absent
+ <<: *aci_bgp_best_path_policy_present
+ state: absent
+ check_mode: true
+ register: cm_remove_bgp_best_path_policy
+
+ - name: Remove BGP best path policy (normal_mode)
+ aci_bgp_best_path_policy:
+ <<: *bgp_best_path_policy_absent
+ register: nm_remove_bgp_best_path_policy
+
+ - name: Remove BGP best path policy - testing idempotency
+ aci_bgp_best_path_policy:
+ <<: *bgp_best_path_policy_absent
+ register: nm_remove_bgp_best_path_policy_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_bgp_best_path_policy is changed
+ - cm_remove_bgp_best_path_policy.proposed == {}
+ - nm_remove_bgp_best_path_policy is changed
+ - nm_remove_bgp_best_path_policy.previous != []
+ - nm_remove_bgp_best_path_policy.method == "DELETE"
+ - nm_remove_bgp_best_path_policy_idempotency is not changed
+ - nm_remove_bgp_best_path_policy_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml
new file mode 100644
index 000000000..0c7cdd77d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_timers_policy/tasks/main.yml
@@ -0,0 +1,155 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a BGP timers policy (check_mode)
+ aci_bgp_timers_policy: &aci_bgp_timers_policy_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ bgp_timers_policy: ansible_bgp_timers_policy_1
+ graceful_restart_controls: complete
+ hold_interval: 360
+ keepalive_interval: 120
+ max_as_limit: 1
+ stale_interval: 600
+ description: BGP timers policy 1 for ansible_tenant tenant
+ state: present
+ check_mode: true
+ register: cm_add_bgp_timers_policy
+
+ - name: Add a BGP timers policy (normal_mode)
+ aci_bgp_timers_policy:
+ <<: *aci_bgp_timers_policy_present
+ register: nm_add_bgp_timers_policy
+
+ - name: Add the first BGP timers policy again - testing idempotency
+ aci_bgp_timers_policy:
+ <<: *aci_bgp_timers_policy_present
+ register: nm_add_bgp_timers_policy_idempotency
+
+ - name: Add a second BGP timers policy (normal_mode)
+ aci_bgp_timers_policy:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bgp_timers_policy: ansible_bgp_timers_policy_2
+ description: BGP timers policy 2 for ansible_tenant tenant
+ state: present
+ register: nm_add_bgp_timers_policy_2
+
+ - name: Asserts for BGP timers policys creation tasks
+ assert:
+ that:
+ - cm_add_bgp_timers_policy is changed
+ - cm_add_bgp_timers_policy.previous == []
+ - cm_add_bgp_timers_policy.current == []
+ - nm_add_bgp_timers_policy is changed
+ - nm_add_bgp_timers_policy.current.0.bgpCtxPol.attributes.name == "ansible_bgp_timers_policy_1"
+ - nm_add_bgp_timers_policy.current.0.bgpCtxPol.attributes.grCtrl == ""
+ - nm_add_bgp_timers_policy.current.0.bgpCtxPol.attributes.holdIntvl == "360"
+ - nm_add_bgp_timers_policy.current.0.bgpCtxPol.attributes.kaIntvl == "120"
+ - nm_add_bgp_timers_policy.current.0.bgpCtxPol.attributes.maxAsLimit == "1"
+ - nm_add_bgp_timers_policy.current.0.bgpCtxPol.attributes.staleIntvl == "600"
+ - nm_add_bgp_timers_policy_idempotency is not changed
+ - nm_add_bgp_timers_policy_2 is changed
+ - nm_add_bgp_timers_policy_2.previous == []
+ - nm_add_bgp_timers_policy_2.current.0.bgpCtxPol.attributes.name == "ansible_bgp_timers_policy_2"
+ - nm_add_bgp_timers_policy_2.current.0.bgpCtxPol.attributes.grCtrl == "helper"
+ - nm_add_bgp_timers_policy_2.current.0.bgpCtxPol.attributes.holdIntvl == "180"
+ - nm_add_bgp_timers_policy_2.current.0.bgpCtxPol.attributes.kaIntvl == "60"
+ - nm_add_bgp_timers_policy_2.current.0.bgpCtxPol.attributes.maxAsLimit == "0"
+ - nm_add_bgp_timers_policy_2.current.0.bgpCtxPol.attributes.staleIntvl == "default"
+
+ - name: Query all BGP timers policies
+ aci_bgp_timers_policy:
+ <<: *aci_info
+ state: query
+ register: query_all_bgp_timers_policy
+
+ - name: Query ansible_bgp_timers_policy_1
+ aci_bgp_timers_policy:
+ <<: *aci_bgp_timers_policy_present
+ state: query
+ register: query_ansible_bgp_timers_policy_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_bgp_timers_policy is not changed
+ - query_all_bgp_timers_policy.current|length >= 2
+ - query_ansible_bgp_timers_policy_1 is not changed
+ - query_ansible_bgp_timers_policy_1.current.0.bgpCtxPol.attributes.name == "ansible_bgp_timers_policy_1"
+ - query_ansible_bgp_timers_policy_1.current.0.bgpCtxPol.attributes.grCtrl == ""
+ - query_ansible_bgp_timers_policy_1.current.0.bgpCtxPol.attributes.holdIntvl == "360"
+ - query_ansible_bgp_timers_policy_1.current.0.bgpCtxPol.attributes.kaIntvl == "120"
+ - query_ansible_bgp_timers_policy_1.current.0.bgpCtxPol.attributes.maxAsLimit == "1"
+ - query_ansible_bgp_timers_policy_1.current.0.bgpCtxPol.attributes.staleIntvl == "600"
+
+ - name: Remove BGP timers policy (check_mode)
+ aci_bgp_timers_policy: &bgp_timers_policy_absent
+ <<: *aci_bgp_timers_policy_present
+ state: absent
+ check_mode: true
+ register: cm_remove_bgp_timers_policy
+
+ - name: Remove BGP timers policy (normal_mode)
+ aci_bgp_timers_policy:
+ <<: *bgp_timers_policy_absent
+ register: nm_remove_bgp_timers_policy
+
+ - name: Remove BGP timers policy - testing idempotency
+ aci_bgp_timers_policy:
+ <<: *bgp_timers_policy_absent
+ register: nm_remove_bgp_timers_policy_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_bgp_timers_policy is changed
+ - cm_remove_bgp_timers_policy.proposed == {}
+ - nm_remove_bgp_timers_policy is changed
+ - nm_remove_bgp_timers_policy.previous != []
+ - nm_remove_bgp_timers_policy.method == "DELETE"
+ - nm_remove_bgp_timers_policy_idempotency is not changed
+ - nm_remove_bgp_timers_policy_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml
index df4c64069..9b43c9cfc 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml
@@ -20,6 +20,9 @@
state: absent
tenant: ansible_test
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
- name: create a snapshot
cisco.aci.aci_config_snapshot: &create_snapshot
<<: *aci_tenant_absent
@@ -49,62 +52,128 @@
state: query
register: snapshots
-- name: sort snapshot list
- set_fact:
- sorted_snapshots: '{{ snapshots.current.0.configSnapshotCont.children | sort(attribute="configSnapshot.attributes.createTime", reverse=True) }}'
-
-- name: compare snapshots
- cisco.aci.aci_config_rollback: &preview_rollback
- <<: *create_snapshot
- state: preview
- compare_export_policy: anstest
- compare_snapshot: "{{ sorted_snapshots[0].configSnapshot.attributes.name }}"
- snapshot: "{{ sorted_snapshots[1].configSnapshot.attributes.name }}"
- register: rollback_preview
-
-- name: rollback to snapshot with missing parameters
- cisco.aci.aci_config_rollback: &aci_rollback
- <<: *create_snapshot
- state: rollback
- snapshot: "{{ sorted_snapshots[1].configSnapshot.attributes.name }}"
- ignore_errors: true
- register: rollback_missing_param
-
-- name: rollback to snapshot
- cisco.aci.aci_config_rollback:
- <<: *aci_rollback
- import_policy: anstest
- import_type: replace
- import_mode: atomic
- register: rollback_rollback
-
-- name: pause execution to let rollback take effect
- pause:
- seconds: 15
-
-- name: ensure tenant doesn't exist after rollback
- cisco.aci.aci_tenant:
- <<: *aci_tenant_absent
- register: tenant_removed
-
-- debug:
- msg: '{{ rollback_preview }}'
-
-- name: rollback assertions
- assert:
- that:
- - rollback_preview is not changed
- - rollback_preview.preview.polUni.children[0].fvTenant.attributes.name == 'ansible_test'
- - rollback_preview.preview.polUni.children[0].fvTenant.attributes.status == 'created'
- - '"snapshots.diff.xml" in rollback_preview.url'
- - rollback_missing_param is failed
- - 'rollback_missing_param.msg == "state is rollback but all of the following are missing: import_policy"'
- - rollback_rollback is changed
- - '"ce2_" in rollback_rollback.sent.configImportP.attributes.fileName'
- - '".tar.gz" in rollback_rollback.sent.configImportP.attributes.fileName'
- - '"ce2_" in rollback_rollback.proposed.configImportP.attributes.fileName'
- - '".tar.gz" in rollback_rollback.proposed.configImportP.attributes.fileName'
- - '"fabric/configimp-anstest.json" in rollback_rollback.url'
- - tenant_removed is not changed
- - tenant_removed.previous == []
- - create_snapshot_annotation_check.current.0.configExportP.attributes.annotation == 'orchestrator:ansible'
+- 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
+ # Snapshot compare does not work for cloud site since only 1 item is returned in configSnapshotCont
+ # TODO further investigate why cloud sites behave differently in saving snapshots
+ - name: verify only one snapshot is returned
+ ansible.builtin.assert:
+ that:
+ - snapshots.current.0.configSnapshotCont.children | length == 1
+
+- 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
+ # Snapshot compare does not work for cloud site since only 1 item is returned in configSnapshotCont
+ - name: sort snapshot list
+ ansible.builtin.set_fact:
+ sorted_snapshots: '{{ snapshots.current.0.configSnapshotCont.children | sort(attribute="configSnapshot.attributes.createTime", reverse=True) }}'
+
+ - name: Uninstall lxml for error checking
+ ansible.builtin.pip: &lxml
+ name: lxml
+ state: absent
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+ - name: Uninstall xmljson for error checking
+ ansible.builtin.pip: &xmljson
+ name: xmljson
+ state: absent
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+ - name: compare snapshots
+ cisco.aci.aci_config_rollback: &preview_rollback
+ <<: *create_snapshot
+ state: preview
+ compare_export_policy: anstest
+ compare_snapshot: "{{ sorted_snapshots[0].configSnapshot.attributes.name }}"
+ snapshot: "{{ sorted_snapshots[1].configSnapshot.attributes.name }}"
+ register: rollback_preview_xml
+
+ - name: Install lxml
+ ansible.builtin.pip:
+ <<: *lxml
+ state: present
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+ - name: Install xmljson
+ ansible.builtin.pip:
+ <<: *xmljson
+ state: present
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+ - name: compare snapshots
+ cisco.aci.aci_config_rollback:
+ <<: *preview_rollback
+ register: rollback_preview_json
+
+ - name: compare snapshots with wrong compare_snapshot (error)
+ cisco.aci.aci_config_rollback:
+ <<: *preview_rollback
+ compare_snapshot: wrong_snap
+ ignore_errors: true
+ register: err_rollback_preview_json
+
+ - name: rollback to snapshot with missing parameters
+ cisco.aci.aci_config_rollback: &aci_rollback
+ <<: *create_snapshot
+ state: rollback
+ snapshot: "{{ sorted_snapshots[1].configSnapshot.attributes.name }}"
+ ignore_errors: true
+ register: rollback_missing_param
+
+ - name: rollback to not existing snapshot for "tar.gz" append and "run-" removal testing
+ cisco.aci.aci_config_rollback:
+ <<: *aci_rollback
+ snapshot: "not-existing-snapshot.tar.gz"
+ import_policy: anstest
+ import_type: replace
+ import_mode: atomic
+ register: not_existing_rollback
+ ignore_errors: true
+
+ - name: rollback to snapshot
+ cisco.aci.aci_config_rollback:
+ <<: *aci_rollback
+ import_policy: anstest
+ import_type: replace
+ import_mode: atomic
+ register: rollback_rollback
+
+ - name: pause execution to let rollback take effect
+ pause:
+ seconds: 15
+
+ - name: ensure tenant doesn't exist after rollback
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_absent
+ register: tenant_removed
+
+ - debug:
+ msg: '{{ rollback_preview_json }}'
+
+ - name: rollback assertions
+ assert:
+ that:
+ - rollback_preview_xml is not changed
+ - '"ansible_test" in rollback_preview_xml.preview'
+ - '"created" in rollback_preview_xml.preview'
+ - '"snapshots.diff.xml" in rollback_preview_xml.url'
+ - err_rollback_preview_json.status == 400
+ - err_rollback_preview_json.response == "HTTP Error 400{{":"}} Bad Request"
+ - rollback_preview_json is not changed
+ - rollback_preview_json.preview.polUni.children[0].fvTenant.attributes.name == 'ansible_test'
+ - rollback_preview_json.preview.polUni.children[0].fvTenant.attributes.status == 'created'
+ - '"snapshots.diff.xml" in rollback_preview_json.url'
+ - rollback_missing_param is failed
+ - 'rollback_missing_param.msg == "state is rollback but all of the following are missing: import_policy"'
+ - rollback_rollback is changed
+ - '"ce2_" in rollback_rollback.sent.configImportP.attributes.fileName'
+ - '".tar.gz" in rollback_rollback.sent.configImportP.attributes.fileName'
+ - '"ce2_" in rollback_rollback.proposed.configImportP.attributes.fileName'
+ - '".tar.gz" in rollback_rollback.proposed.configImportP.attributes.fileName'
+ - '"fabric/configimp-anstest.json" in rollback_rollback.url'
+ - tenant_removed is not changed
+ - tenant_removed.previous == []
+ - create_snapshot_annotation_check.current.0.configExportP.attributes.annotation == 'orchestrator:ansible'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.crt
new file mode 100644
index 000000000..cfac5531e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICODCCAaGgAwIBAgIJAIt8XMntue0VMA0GCSqGSIb3DQEBCwUAMDQxDjAMBgNV
+BAMMBUFkbWluMRUwEwYDVQQKDAxZb3VyIENvbXBhbnkxCzAJBgNVBAYTAlVTMCAX
+DTE4MDEwOTAwNTk0NFoYDzIxMTcxMjE2MDA1OTQ0WjA0MQ4wDAYDVQQDDAVBZG1p
+bjEVMBMGA1UECgwMWW91ciBDb21wYW55MQswCQYDVQQGEwJVUzCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAohG/7axtt7CbSaMP7r+2mhTKbNgh0Ww36C7Ta14i
+v+VmLyKkQHnXinKGhp6uy3Nug+15a+eIu7CrgpBVMQeCiWfsnwRocKcQJWIYDrWl
+XHxGQn31yYKR6mylE7Dcj3rMFybnyhezr5D8GcP85YRPmwG9H2hO/0Y1FUnWu9Iw
+AQkCAwEAAaNQME4wHQYDVR0OBBYEFD0jLXfpkrU/ChzRvfruRs/fy1VXMB8GA1Ud
+IwQYMBaAFD0jLXfpkrU/ChzRvfruRs/fy1VXMAwGA1UdEwQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADgYEAOmvre+5tgZ0+F3DgsfxNQqLTrGiBgGCIymPkP/cBXXkNuJyl
+3ac7tArHQc7WEA4U2R2rZbEq8FC3UJJm4nUVtCPvEh3G9OhN2xwYev79yt6pIn/l
+KU0Td2OpVyo0eLqjoX5u2G90IBWzhyjFbo+CcKMrSVKj1YOdG0E3OuiJf00=
+-----END CERTIFICATE-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.key
new file mode 100644
index 000000000..63bb00cc0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/pki/admin.key
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKIRv+2sbbewm0mj
+D+6/tpoUymzYIdFsN+gu02teIr/lZi8ipEB514pyhoaerstzboPteWvniLuwq4KQ
+VTEHgoln7J8EaHCnECViGA61pVx8RkJ99cmCkepspROw3I96zBcm58oXs6+Q/BnD
+/OWET5sBvR9oTv9GNRVJ1rvSMAEJAgMBAAECgYByu3QO0qF9h7X3JEu0Ld4cKBnB
+giQ2uJC/et7KxIJ/LOvw9GopBthyt27KwG1ntBkJpkTuAaQHkyNns7vLkNB0S0IR
++owVFEcKYq9VCHTaiQU8TDp24gN+yPTrpRuH8YhDVq5SfVdVuTMgHVQdj4ya4VlF
+Gj+a7+ipxtGiLsVGrQJBAM7p0Fm0xmzi+tBOASUAcVrPLcteFIaTBFwfq16dm/ON
+00Khla8Et5kMBttTbqbukl8mxFjBEEBlhQqb6EdQQ0sCQQDIhHx1a9diG7y/4DQA
+4KvR3FCYwP8PBORlSamegzCo+P1OzxiEo0amX7yQMA5UyiP/kUsZrme2JBZgna8S
+p4R7AkEAr7rMhSOPUnMD6V4WgsJ5g1Jp5kqkzBaYoVUUSms5RASz4+cwJVCwTX91
+Y1jcpVIBZmaaY3a0wrx13ajEAa0dOQJBAIpjnb4wqpsEh7VpmJqOdSdGxb1XXfFQ
+sA0T1OQYqQnFppWwqrxIL+d9pZdiA1ITnNqyvUFBNETqDSOrUHwwb2cCQGArE+vu
+ffPUWQ0j+fiK+covFG8NL7H+26NSGB5+Xsn9uwOGLj7K/YT6CbBtr9hJiuWjM1Al
+0V4ltlTuu2mTMaw=
+-----END PRIVATE KEY-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml
index 22bcbcb79..c9415a86d 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml
@@ -146,3 +146,82 @@
- delete_idempotent.previous == []
- delete_missing_param is failed
- 'delete_missing_param.msg == "state is absent but all of the following are missing: snapshot"'
+
+# Create, query and delete snapshot with certificate authentication Ref# 427
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ validate_certs: "{{ aci_validate_certs | default(false) }}"
+ use_ssl: "{{ aci_use_ssl | default(true) }}"
+ use_proxy: "{{ aci_use_proxy | default(true) }}"
+ output_level: debug
+
+- name: Add a user certificate to be used in the test
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ password: "{{ aci_password }}"
+ aaa_user: "{{ aci_username }}"
+ name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+
+- name: create a snapshot using the private key
+ cisco.aci.aci_config_snapshot:
+ <<: *aci_info
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ export_policy: anstest
+ include_secure: false
+ format: json
+ description: ansible test
+ register: create_private_key
+
+- name: creation assertion tests with private key
+ assert:
+ that:
+ - create_private_key is not failed
+ - create_private_key is changed
+ - create_private_key.sent.configExportP.attributes.adminSt == "triggered"
+
+- name: query the snapshot using the private key
+ cisco.aci.aci_config_snapshot:
+ <<: *aci_info
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ export_policy: anstest
+ state: query
+ register: query_private_key
+
+- name: generate snapshot name using query_private_key
+ set_fact:
+ test_snapshot_private_key: "{{ query_private_key.current.0.configSnapshotCont.children.0.configSnapshot.attributes.rn.strip('snapshot-') }}"
+
+- name: query assertion tests with private key
+ assert:
+ that:
+ - query_private_key is not failed
+ - query_private_key is not changed
+ - '"snapshots-[uni/fabric/configexp-anstest].json" in query_private_key.url'
+
+- name: delete using the private key
+ cisco.aci.aci_config_snapshot:
+ <<: *aci_info
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ export_policy: anstest
+ snapshot: "{{ test_snapshot_private_key }}"
+ state: absent
+ register: delete_snapshot_private_key
+
+- name: delete assertion tests with the private key
+ assert:
+ that:
+ - delete_snapshot_private_key is not failed
+ - delete_snapshot_private_key is changed
+
+- name: Remove the user certificate
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ password: "{{ aci_password }}"
+ aaa_user: "{{ aci_username }}"
+ name: admin
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml
index f7e69e620..d21571692 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml
@@ -129,6 +129,13 @@
state: query
register: query_binding
+ - name: query binding with non_existing subject
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_present
+ state: query
+ subject: non_existing
+ register: query_binding_non_existing_subject
+
- name: query assertions
assert:
that:
@@ -137,6 +144,7 @@
- query_all.current.0.vzRsSubjFiltAtt is defined
- query_binding is not changed
- query_binding.current != []
+ - query_binding_non_existing_subject.current == []
- name: delete subject filter binding - check mode works
cisco.aci.aci_contract_subject_to_filter: &aci_subject_filter_absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml
index 920a24969..da10cc2d8 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml
@@ -1,5 +1,6 @@
# Test code for the ACI modules
# Copyright: (c) 2021, Tim Cragg(@timcragg)
+# Copyright: (c) 2023, Akini Ross(@akinross)
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -26,6 +27,12 @@
tenant: ansible_tenant
state: absent
+- name: Delete Global DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ name: ansible_global_dhcp_relay
+ state: absent
+
- name: Add a new tenant
aci_tenant:
<<: *aci_info
@@ -91,6 +98,32 @@
- update_dhcp_relay.current.0.dhcpRelayP.attributes.owner == "tenant"
- update_dhcp_relay.current.0.dhcpRelayP.attributes.descr == "New Ansible DHCP Relay"
+- name: Add another DHCP relay policy for query all
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay_2
+ state: present
+
+# CREATE GLOBAL DHCP RELAY
+- name: Add a new Global DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ name: ansible_global_dhcp_relay
+ description: Ansible Global DHCP Relay
+ state: present
+ register: add_global_dhcp_relay
+
+- name: Verify Global DHCP Relay creation
+ assert:
+ that:
+ - add_global_dhcp_relay is changed
+ - add_global_dhcp_relay.current.0.dhcpRelayP.attributes.annotation == 'orchestrator:ansible'
+ - add_global_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay"
+ - add_global_dhcp_relay.current.0.dhcpRelayP.attributes.name == "ansible_global_dhcp_relay"
+ - add_global_dhcp_relay.current.0.dhcpRelayP.attributes.owner == "infra"
+ - add_global_dhcp_relay.current.0.dhcpRelayP.attributes.descr == "Ansible Global DHCP Relay"
+
# QUERY DHCP RELAY
- name: Query DHCP relay policy
cisco.aci.aci_dhcp_relay:
@@ -120,6 +153,36 @@
assert:
that:
- query_dhcp_relay_all is not changed
+ - query_dhcp_relay_all.current.0.fvTenant.children | length >= 2
+
+# QUERY GLOBAL DHCP RELAY
+- name: Query Global DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ name: ansible_global_dhcp_relay
+ state: query
+ register: query_global_dhcp_relay
+
+- name: Verify Global DHCP Relay query
+ assert:
+ that:
+ - query_global_dhcp_relay is not changed
+ - query_global_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay"
+ - query_global_dhcp_relay.current.0.dhcpRelayP.attributes.name == "ansible_global_dhcp_relay"
+ - query_global_dhcp_relay.current.0.dhcpRelayP.attributes.owner == "infra"
+ - query_global_dhcp_relay.current.0.dhcpRelayP.attributes.descr == "Ansible Global DHCP Relay"
+
+- name: Query all DHCP relays
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ state: query
+ register: query_global_dhcp_relay_all
+
+- name: Verify query idempotence for Global DHCP Relay
+ assert:
+ that:
+ - query_global_dhcp_relay_all is not changed
+ - query_global_dhcp_relay_all.current | length >= 3
# DELETE DHCP RELAY
- name: Delete DHCP relay policy
@@ -153,6 +216,24 @@
that:
- delete_dhcp_relay_again is not changed
+# DELETE GLOBAL DHCP RELAY
+- name: Delete Global DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ name: ansible_global_dhcp_relay
+ state: absent
+ register: delete_global_dhcp_relay
+
+- name: Verify Global DHCP Relay deletion
+ assert:
+ that:
+ - delete_global_dhcp_relay is changed
+ - delete_global_dhcp_relay.current == []
+ - delete_global_dhcp_relay.previous.0.dhcpRelayP.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay"
+ - delete_global_dhcp_relay.previous.0.dhcpRelayP.attributes.name == "ansible_global_dhcp_relay"
+ - delete_global_dhcp_relay.previous.0.dhcpRelayP.attributes.owner == "infra"
+ - delete_global_dhcp_relay.previous.0.dhcpRelayP.attributes.descr == "Ansible Global DHCP Relay"
+
# CLEAN ENVIRONMENT AGAIN
- name: Remove the ansible_tenant
aci_tenant:
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml
index 2edc45e51..c133e23ba 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml
@@ -1,5 +1,6 @@
# Test code for the ACI modules
# Copyright: (c) 2021, Tim Cragg(@timcragg)
+# Copyright: (c) 2023, Akini Ross (@akinross)
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -29,6 +30,12 @@
tenant: ansible_tenant
state: absent
+- name: Delete Global DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ name: ansible_global_dhcp_relay
+ state: absent
+
- name: Remove l2ext domain
cisco.aci.aci_domain:
<<: *aci_info
@@ -153,6 +160,15 @@
description: Ansible DHCP Relay
state: present
+ # CREATE GLOBAL DHCP RELAY
+ - name: Add a new Global DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ name: ansible_global_dhcp_relay
+ description: Ansible Global DHCP Relay
+ state: present
+ register: add_global_dhcp_relay
+
# CREATE DHCP RELAY PROVIDERS
- name: Add a new DHCP relay App EPG provider
cisco.aci.aci_dhcp_relay_provider:
@@ -361,7 +377,6 @@
- update_dn_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.53"
- update_dn_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
-
# QUERY DHCP RELAY PROVIDERS
- name: Query DHCP relay App EPG provider
cisco.aci.aci_dhcp_relay_provider:
@@ -405,6 +420,13 @@
dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
state: query
register: query_dn_relay_provider
+
+ - name: Query all DHCP relays in ansible_tenant
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: query
+ register: query_all_relay_provider
- name: Confirm DHCP relay provider query
assert:
@@ -425,6 +447,161 @@
- query_dn_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2]"
- query_dn_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.53"
- query_dn_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ - query_all_relay_provider is not changed
+ - query_all_relay_provider.current.0.fvTenant.children.0.dhcpRelayP.children | length >= 4
+
+ # CREATE GLOBAL DHCP RELAY PROVIDERS
+ - name: Add a new Global DHCP relay App EPG provider without provider tenant (error)
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ dhcp_server_addr: 10.20.30.40
+ state: present
+ ignore_errors: true
+ register: err_global_epg_relay_provider
+
+ - name: Add a new Global DHCP relay App EPG provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ epg_type: epg
+ provider_tenant: ansible_tenant
+ anp: ansible_ap
+ app_epg: ansible_epg
+ dhcp_server_addr: 10.20.30.40
+ state: present
+ register: add_global_epg_relay_provider
+
+ - name: Add a new Global DHCP relay L2out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ epg_type: l2_external
+ provider_tenant: ansible_tenant
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ dhcp_server_addr: 10.20.30.41
+ state: present
+ register: add_global_l2_relay_provider
+
+ - name: Add a new Global DHCP relay L3out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ epg_type: l3_external
+ provider_tenant: ansible_tenant
+ l3out_name: ansible_l3out
+ external_net: ansible_l3out_ext_net
+ dhcp_server_addr: 10.20.30.42
+ state: present
+ register: add_global_l3_relay_provider
+
+ - name: Add a new Global DHCP relay dn provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ epg_type: dn
+ dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ dhcp_server_addr: 10.20.30.43
+ state: present
+ register: add_global_dn_relay_provider
+
+ - name: Confirm Global DHCP relay provider creation
+ assert:
+ that:
+ - err_global_epg_relay_provider is failed
+ - err_global_epg_relay_provider.msg == "provider_tenant is required when epg_type is epg"
+ - add_global_epg_relay_provider is changed
+ - add_global_epg_relay_provider.current.0.dhcpRsProv.attributes.annotation == 'orchestrator:ansible'
+ - add_global_epg_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]"
+ - add_global_epg_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.40"
+ - add_global_epg_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - add_global_l2_relay_provider is changed
+ - add_global_l2_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - add_global_l2_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.41"
+ - add_global_l2_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - add_global_l3_relay_provider is changed
+ - add_global_l3_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - add_global_l3_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.42"
+ - add_global_l3_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - add_global_dn_relay_provider is changed
+ - add_global_dn_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2]"
+ - add_global_dn_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.43"
+ - add_global_dn_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+
+ # QUERY GLOBAL DHCP RELAY PROVIDERS
+ - name: Query Global DHCP relay App EPG provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ provider_tenant: ansible_tenant
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ state: query
+ register: query_global_epg_relay_provider
+
+ - name: Query Global DHCP relay L2out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ provider_tenant: ansible_tenant
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ state: query
+ register: query_global_l2_relay_provider
+
+ - name: Query Global DHCP relay L3out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ provider_tenant: ansible_tenant
+ epg_type: l3_external
+ l3out_name: ansible_l3out
+ external_net: ansible_l3out_ext_net
+ state: query
+ register: query_global_l3_relay_provider
+
+ - name: Query Global DHCP relay dn provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ epg_type: dn
+ dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ state: query
+ register: query_global_dn_relay_provider
+
+ - name: Query all Global DHCP relay providers
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ state: query
+ register: query_global_all_relay_provider
+
+ - name: Confirm DHCP relay provider query
+ assert:
+ that:
+ - query_global_epg_relay_provider is not changed
+ - query_global_epg_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]"
+ - query_global_epg_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.40"
+ - query_global_epg_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - query_global_l2_relay_provider is not changed
+ - query_global_l2_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - query_global_l2_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.41"
+ - query_global_l2_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - query_global_l3_relay_provider is not changed
+ - query_global_l3_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - query_global_l3_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.42"
+ - query_global_l3_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - query_global_dn_relay_provider is not changed
+ - query_global_dn_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2]"
+ - query_global_dn_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.43"
+ - query_global_dn_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ - query_global_all_relay_provider is not changed
+ - query_global_all_relay_provider.current | length >= 8
# DELETE DHCP RELAY PROVIDERS
- name: Delete DHCP relay App EPG provider
@@ -471,7 +648,6 @@
state: absent
register: delete_dn_relay_provider
-
- name: Confirm DHCP relay provider removal
assert:
that:
@@ -548,6 +724,72 @@
- delete_l3_relay_provider_again is not changed
- delete_dn_relay_provider_again is not changed
+ # DELETE GLOBAL DHCP RELAY PROVIDERS
+ - name: Delete Global DHCP relay App EPG provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ provider_tenant: ansible_tenant
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ state: absent
+ register: delete_global_epg_relay_provider
+
+ - name: Delete Global DHCP relay L2out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ provider_tenant: ansible_tenant
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ state: absent
+ register: delete_global_l2_relay_provider
+
+ - name: Delete Global DHCP relay L3out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ provider_tenant: ansible_tenant
+ epg_type: l3_external
+ l3out_name: ansible_l3out
+ external_net: ansible_l3out_ext_net
+ state: absent
+ register: delete_global_l3_relay_provider
+
+ - name: Delete Global DHCP relay dn provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ relay_policy: ansible_global_dhcp_relay
+ epg_type: dn
+ dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ state: absent
+ register: delete_global_dn_relay_provider
+
+ - name: Confirm DHCP relay provider removal
+ assert:
+ that:
+ - delete_global_epg_relay_provider is changed
+ - delete_global_epg_relay_provider.current == []
+ - delete_global_epg_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]"
+ - delete_global_epg_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.40"
+ - delete_global_epg_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - delete_global_l2_relay_provider is changed
+ - delete_global_l2_relay_provider.current == []
+ - delete_global_l2_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - delete_global_l2_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.41"
+ - delete_global_l2_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - delete_global_l3_relay_provider is changed
+ - delete_global_l3_relay_provider.current == []
+ - delete_global_l3_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - delete_global_l3_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.42"
+ - delete_global_l3_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - delete_global_dn_relay_provider is changed
+ - delete_global_dn_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/infra/relayp-ansible_global_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2]"
+ - delete_global_dn_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.43"
+ - delete_global_dn_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+
# CLEAN ENVIRONMENT AGAIN
- name: Remove the ansible_tenant
aci_tenant:
@@ -555,6 +797,12 @@
tenant: ansible_tenant
state: absent
+ - name: Delete Global DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ name: ansible_global_dhcp_relay
+ state: absent
+
- name: Remove l2ext domain
cisco.aci.aci_domain:
<<: *aci_info
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml
index 2d3de4dd0..af9c1026b 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml
@@ -26,7 +26,6 @@
<<: *aci_info
profile_name: ansible_dns_profile
state: absent
- delegate_to: localhost
# ADD DNS PROFILE
- name: Add DNS profile
@@ -34,7 +33,6 @@
<<: *aci_info
profile_name: ansible_dns_profile
state: present
- delegate_to: localhost
# ADD DNS DOMAIN
- name: Add a new DNS domain
@@ -44,7 +42,6 @@
domain: example.com
default: false
state: present
- delegate_to: localhost
register: add_dns_domain
- name: Verify DNS domain creation
@@ -64,7 +61,6 @@
domain: example.com
default: false
state: present
- delegate_to: localhost
register: add_dns_domain_again
- name: Verify DNS domain creation idempotence
@@ -83,7 +79,6 @@
domain: example.com
default: true
state: present
- delegate_to: localhost
register: update_dns_domain
- name: Verify DNS domain update
@@ -101,7 +96,6 @@
dns_profile: ansible_dns_profile
domain: example.com
state: query
- delegate_to: localhost
register: query_dns_domain
- name: Verify DNS domain attributes
@@ -118,7 +112,6 @@
<<: *aci_info
dns_profile: ansible_dns_profile
state: query
- delegate_to: localhost
register: query_dns_domain_all
- name: Verify DNS domain query idempotence
@@ -133,7 +126,6 @@
dns_profile: ansible_dns_profile
domain: example.com
state: absent
- delegate_to: localhost
register: delete_dns_domain
- name: Verify DNS domain deletion
@@ -152,7 +144,6 @@
dns_profile: ansible_dns_profile
domain: example.com
state: absent
- delegate_to: localhost
register: delete_dns_domain_again
- name: Verify DNS domain deletion idempotence
@@ -166,4 +157,3 @@
<<: *aci_info
profile_name: ansible_dns_profile
state: absent
- delegate_to: localhost
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml
index 8deca651c..3e31d2b52 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml
@@ -26,7 +26,6 @@
<<: *aci_info
profile_name: ansible_dns_profile
state: absent
- delegate_to: localhost
# ADD DNS PROFILE
- name: Add DNS profile
@@ -34,7 +33,6 @@
<<: *aci_info
profile_name: ansible_dns_profile
state: present
- delegate_to: localhost
# ADD DNS PROVIDER
- name: Add a new DNS provider
@@ -44,7 +42,6 @@
addr: 10.20.30.40
preferred: false
state: present
- delegate_to: localhost
register: add_dns_provider
- name: Verify DNS provider creation
@@ -64,7 +61,6 @@
addr: 10.20.30.40
preferred: false
state: present
- delegate_to: localhost
register: add_dns_provider_again
- name: Verify DNS provider creation idempotence
@@ -83,7 +79,6 @@
addr: 10.20.30.40
preferred: true
state: present
- delegate_to: localhost
register: update_dns_provider
- name: Verify DNS provider update
@@ -101,7 +96,6 @@
dns_profile: ansible_dns_profile
addr: 10.20.30.40
state: query
- delegate_to: localhost
register: query_dns_provider
- name: Verify DNS provider attributes
@@ -118,7 +112,6 @@
<<: *aci_info
dns_profile: ansible_dns_profile
state: query
- delegate_to: localhost
register: query_dns_provider_all
- name: Verify DNS provider query idempotence
@@ -133,7 +126,6 @@
dns_profile: ansible_dns_profile
addr: 10.20.30.40
state: absent
- delegate_to: localhost
register: delete_dns_provider
- name: Verify DNS provider deletion
@@ -152,7 +144,6 @@
dns_profile: ansible_dns_profile
addr: 10.20.30.40
state: absent
- delegate_to: localhost
register: delete_dns_provider_again
- name: Verify DNS provider deletion idempotence
@@ -166,4 +157,3 @@
<<: *aci_info
profile_name: ansible_dns_profile
state: absent
- delegate_to: localhost
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml
index 8c31fd4cc..ab10856a8 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml
@@ -3,6 +3,22 @@
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ ansible.builtin.set_fact:
+ aci_info: &aci_info
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_password }}'
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
- name: Verify Cloud and Non-Cloud Sites in use.
include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
@@ -12,41 +28,36 @@
# CLEAN ENVIRONMENT
- name: Remove domain to VLAN pool binding
cisco.aci.aci_domain_to_vlan_pool: &binding_absent
- 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") }}'
+ <<: *aci_info
domain: phys_dom
domain_type: phys
pool: test_pool
pool_allocation_mode: dynamic
state: absent
- - name: Remove physical domain
+ - name: Remove domains
cisco.aci.aci_domain:
- 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") }}'
- domain: phys_dom
- domain_type: phys
+ <<: *aci_info
+ domain: "{{ item.domain }}"
+ domain_type: "{{ item.domain_type }}"
+ state: absent
+ loop:
+ - {domain: phys_dom, domain_type: phys}
+ - {domain: fc_dom, domain_type: fc}
+ - {domain: l2dom_dom, domain_type: l2dom}
+ - {domain: l3dom_dom, domain_type: l3dom}
+
+ - name: Remove VMM domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: anstest
+ domain_type: vmm
+ vm_provider: vmware
state: absent
- name: Create VLAN pool
cisco.aci.aci_vlan_pool:
- 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") }}'
+ <<: *aci_info
pool: test_pool
pool_allocation_mode: dynamic
description: Test VLAN pool
@@ -56,13 +67,7 @@
# ADD BINDING
- name: Add domain to VLAN pool binding (check_mode)
cisco.aci.aci_domain_to_vlan_pool: &binding_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: '{{ aci_output_level | default("info") }}'
+ <<: *aci_info
domain: phys_dom
domain_type: phys
pool: test_pool
@@ -105,17 +110,67 @@
- cm_add_binding_again is not changed
- nm_add_binding_again is not changed
+ - name: Add domain to VLAN pool binding with domain type not vmm and with vm provider (error)
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_present
+ domain: phys_dom
+ domain_type: phys
+ vm_provider: vmware
+ ignore_errors: true
+ register: err_not_vmm_with_vm_provider
+
+ - name: Add domain to VLAN pool binding with domain type fc
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_present
+ domain: fc_dom
+ domain_type: fc
+ pool_allocation_mode: static
+ register: nm_fc_type
+
+ - name: Add domain to VLAN pool binding with domain type l2dom
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_present
+ domain: l2dom_dom
+ domain_type: l2dom
+ register: nm_l2dom_type
+
+ - name: Add domain to VLAN pool binding with domain type l3dom
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_present
+ domain: l3dom_dom
+ domain_type: l3dom
+ register: nm_l3dom_type
+
+ - name: Add domain to VLAN pool binding with domain type vmm
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_present
+ domain: anstest
+ domain_type: vmm
+ vm_provider: vmware
+ register: nm_vmm_type
+
+ - name: Verify bindings with domain types
+ assert:
+ that:
+ - err_not_vmm_with_vm_provider is not changed
+ - err_not_vmm_with_vm_provider.msg == "Domain type 'phys' cannot have a 'vm_provider'"
+ - nm_fc_type is changed
+ - nm_fc_type.current.0.fcDomP.attributes.dn == "uni/fc-fc_dom"
+ - nm_fc_type.current.0.fcDomP.children.0.infraRsVlanNs.attributes.tDn == "uni/infra/vlanns-[test_pool]-static"
+ - nm_l2dom_type is changed
+ - nm_l2dom_type.current.0.l2extDomP.attributes.dn == "uni/l2dom-l2dom_dom"
+ - nm_l2dom_type.current.0.l2extDomP.children.0.infraRsVlanNs.attributes.tDn == "uni/infra/vlanns-[test_pool]-dynamic"
+ - nm_l3dom_type is changed
+ - nm_l3dom_type.current.0.l3extDomP.attributes.dn == "uni/l3dom-l3dom_dom"
+ - nm_l3dom_type.current.0.l3extDomP.children.0.infraRsVlanNs.attributes.tDn == "uni/infra/vlanns-[test_pool]-dynamic"
+ - nm_vmm_type is changed
+ - nm_vmm_type.current.0.vmmDomP.attributes.dn == "uni/vmmp-VMware/dom-anstest"
+ - nm_vmm_type.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == "uni/infra/vlanns-[test_pool]-dynamic"
# QUERY ALL BINDINGS
- name: Query all domain to VLAN pool bindings (check_mode)
cisco.aci.aci_domain_to_vlan_pool: &binding_query
- 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") }}'
+ <<: *aci_info
domain_type: phys
pool_allocation_mode: dynamic
state: query
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml
index 7bdc332c5..06df26232 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml
@@ -1,20 +1,97 @@
-- name: ensure vsan pool exists for tests to kick off
+- 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("info") }}'
+
+- name: create vsan pool anstest
cisco.aci.aci_encap_pool: &aci_pool_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: '{{ aci_output_level | default("info") }}'
+ <<: *aci_info
+ pool: anstest
+ pool_type: vsan
+ pool_allocation_mode: static
+ description: Ansible Test
+
+- name: add range to vsan pool anstest (check mode)
+ cisco.aci.aci_encap_pool_range: &aci_vsan_range
+ <<: *aci_info
pool: anstest
pool_type: vsan
- allocation_mode: static
+ pool_allocation_mode: static
+ range_start: 20
+ range_end: 40
description: Ansible Test
- state: present
+ check_mode: true
+ register: cm_vsan_present
+
+- name: add range to vsan pool anstest (error)
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vsan_range
+ range_start: 4092
+ range_end: 4099
+ register: err_vsan_range
+ ignore_errors: true
+
+- name: add range to vsan pool anstest
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vsan_range
+ register: nm_vsan_present
+
+- name: add range to vsan pool anstest again
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vsan_range
+ register: nm_vsan_present_again
+
+- name: delete range from vsan pool anstest
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vsan_range
+ state: absent
+ register: rm_vsan_present
+
+- name: present assertions
+ ansible.builtin.assert:
+ that:
+ - cm_vsan_present is changed
+ - cm_vsan_present.current == []
+ - cm_vsan_present.proposed.fvnsVsanEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - cm_vsan_present.proposed.fvnsVsanEncapBlk.attributes.descr == "Ansible Test"
+ - cm_vsan_present.proposed.fvnsVsanEncapBlk.attributes.dn == "uni/infra/vsanns-[anstest]-static/vsanfrom-[vsan-20]-to-[vsan-40]"
+ - cm_vsan_present.proposed.fvnsVsanEncapBlk.attributes.from == "vsan-20"
+ - cm_vsan_present.proposed.fvnsVsanEncapBlk.attributes.to == "vsan-40"
+ - err_vsan_range is not changed
+ - err_vsan_range.msg == 'vsan pools must have "range_start" and "range_end" values between 1 and 4093'
+ - nm_vsan_present is changed
+ - nm_vsan_present.previous == []
+ - nm_vsan_present.current.0.fvnsVsanEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - nm_vsan_present.current.0.fvnsVsanEncapBlk.attributes.descr == "Ansible Test"
+ - nm_vsan_present.current.0.fvnsVsanEncapBlk.attributes.dn == "uni/infra/vsanns-[anstest]-static/vsanfrom-[vsan-20]-to-[vsan-40]"
+ - nm_vsan_present.current.0.fvnsVsanEncapBlk.attributes.from == "vsan-20"
+ - nm_vsan_present.current.0.fvnsVsanEncapBlk.attributes.to == "vsan-40"
+ - nm_vsan_present_again is not changed
+ - nm_vsan_present_again.previous.0.fvnsVsanEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - nm_vsan_present_again.previous.0.fvnsVsanEncapBlk.attributes.descr == "Ansible Test"
+ - nm_vsan_present_again.previous.0.fvnsVsanEncapBlk.attributes.dn == "uni/infra/vsanns-[anstest]-static/vsanfrom-[vsan-20]-to-[vsan-40]"
+ - nm_vsan_present_again.previous.0.fvnsVsanEncapBlk.attributes.from == "vsan-20"
+ - nm_vsan_present_again.previous.0.fvnsVsanEncapBlk.attributes.to == "vsan-40"
+ - nm_vsan_present_again.current.0.fvnsVsanEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - nm_vsan_present_again.current.0.fvnsVsanEncapBlk.attributes.descr == "Ansible Test"
+ - nm_vsan_present_again.current.0.fvnsVsanEncapBlk.attributes.dn == "uni/infra/vsanns-[anstest]-static/vsanfrom-[vsan-20]-to-[vsan-40]"
+ - nm_vsan_present_again.current.0.fvnsVsanEncapBlk.attributes.from == "vsan-20"
+ - nm_vsan_present_again.current.0.fvnsVsanEncapBlk.attributes.to == "vsan-40"
+ - rm_vsan_present is changed
+ - rm_vsan_present.previous.0.fvnsVsanEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - rm_vsan_present.previous.0.fvnsVsanEncapBlk.attributes.descr == "Ansible Test"
+ - rm_vsan_present.previous.0.fvnsVsanEncapBlk.attributes.dn == "uni/infra/vsanns-[anstest]-static/vsanfrom-[vsan-20]-to-[vsan-40]"
+ - rm_vsan_present.previous.0.fvnsVsanEncapBlk.attributes.from == "vsan-20"
+ - rm_vsan_present.previous.0.fvnsVsanEncapBlk.attributes.to == "vsan-40"
+ - rm_vsan_present.current == []
-- name: cleanup vsan pool
+- name: delete vsan pool anstest
cisco.aci.aci_encap_pool:
<<: *aci_pool_present
state: absent
- when: pool_present is changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml
index e5e301916..43a4ff788 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml
@@ -1,19 +1,104 @@
-- name: ensure vxlan pool exists for tests to kick off
+- 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("info") }}'
+
+- name: create vxlan pool anstest
cisco.aci.aci_encap_pool: &aci_pool_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: '{{ aci_output_level | default("info") }}'
+ <<: *aci_info
+ pool: anstest
+ pool_type: vxlan
+ description: Ansible Test
+
+- name: add range to vxlan pool anstest (check mode)
+ cisco.aci.aci_encap_pool_range: &aci_vxlan_range
+ <<: *aci_info
pool: anstest
pool_type: vxlan
+ range_start: 5000
+ range_end: 5010
description: Ansible Test
- state: present
+ check_mode: true
+ register: cm_vxlan_present
+
+- name: add range to vxlan pool anstest with pool_allocation_mode (error)
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vxlan_range
+ allocation_mode: static
+ register: err_vxlan_pool_alloc
+ ignore_errors: true
+
+- name: add range to vxlan pool anstest (error)
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vxlan_range
+ range_start: 4092
+ range_end: 4099
+ register: err_vxlan_range
+ ignore_errors: true
+
+- name: add range to vxlan pool anstest
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vxlan_range
+ register: nm_vxlan_present
+
+- name: add range to vxlan pool anstest again
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vxlan_range
+ register: nm_vxlan_present_again
+
+- name: delete range from vxlan pool anstest
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_vxlan_range
+ state: absent
+ register: rm_vxlan_present
+
+- name: present assertions
+ ansible.builtin.assert:
+ that:
+ - cm_vxlan_present is changed
+ - cm_vxlan_present.current == []
+ - cm_vxlan_present.proposed.fvnsEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - cm_vxlan_present.proposed.fvnsEncapBlk.attributes.descr == "Ansible Test"
+ - cm_vxlan_present.proposed.fvnsEncapBlk.attributes.dn == "uni/infra/vxlanns-anstest/from-[vxlan-5000]-to-[vxlan-5010]"
+ - cm_vxlan_present.proposed.fvnsEncapBlk.attributes.from == "vxlan-5000"
+ - cm_vxlan_present.proposed.fvnsEncapBlk.attributes.to == "vxlan-5010"
+ - err_vxlan_pool_alloc is not changed
+ - err_vxlan_pool_alloc.msg == 'vxlan pools do not support setting the "allocation_mode"; please omit this parameter for vxlan pools'
+ - err_vxlan_range is not changed
+ - err_vxlan_range.msg == 'vxlan pools must have "range_start" and "range_end" values between 5000 and 16777215'
+ - nm_vxlan_present is changed
+ - nm_vxlan_present.previous == []
+ - nm_vxlan_present.current.0.fvnsEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - nm_vxlan_present.current.0.fvnsEncapBlk.attributes.descr == "Ansible Test"
+ - nm_vxlan_present.current.0.fvnsEncapBlk.attributes.dn == "uni/infra/vxlanns-anstest/from-[vxlan-5000]-to-[vxlan-5010]"
+ - nm_vxlan_present.current.0.fvnsEncapBlk.attributes.from == "vxlan-5000"
+ - nm_vxlan_present.current.0.fvnsEncapBlk.attributes.to == "vxlan-5010"
+ - nm_vxlan_present_again is not changed
+ - nm_vxlan_present_again.previous.0.fvnsEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - nm_vxlan_present_again.previous.0.fvnsEncapBlk.attributes.descr == "Ansible Test"
+ - nm_vxlan_present_again.previous.0.fvnsEncapBlk.attributes.dn == "uni/infra/vxlanns-anstest/from-[vxlan-5000]-to-[vxlan-5010]"
+ - nm_vxlan_present_again.previous.0.fvnsEncapBlk.attributes.from == "vxlan-5000"
+ - nm_vxlan_present_again.previous.0.fvnsEncapBlk.attributes.to == "vxlan-5010"
+ - nm_vxlan_present_again.current.0.fvnsEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - nm_vxlan_present_again.current.0.fvnsEncapBlk.attributes.descr == "Ansible Test"
+ - nm_vxlan_present_again.current.0.fvnsEncapBlk.attributes.dn == "uni/infra/vxlanns-anstest/from-[vxlan-5000]-to-[vxlan-5010]"
+ - nm_vxlan_present_again.current.0.fvnsEncapBlk.attributes.from == "vxlan-5000"
+ - nm_vxlan_present_again.current.0.fvnsEncapBlk.attributes.to == "vxlan-5010"
+ - rm_vxlan_present is changed
+ - rm_vxlan_present.previous.0.fvnsEncapBlk.attributes.annotation == "orchestrator:ansible"
+ - rm_vxlan_present.previous.0.fvnsEncapBlk.attributes.descr == "Ansible Test"
+ - rm_vxlan_present.previous.0.fvnsEncapBlk.attributes.dn == "uni/infra/vxlanns-anstest/from-[vxlan-5000]-to-[vxlan-5010]"
+ - rm_vxlan_present.previous.0.fvnsEncapBlk.attributes.from == "vxlan-5000"
+ - rm_vxlan_present.previous.0.fvnsEncapBlk.attributes.to == "vxlan-5010"
+ - rm_vxlan_present.current == []
-- name: cleanup vxlan pool
+- name: delete vxlan pool anstest
cisco.aci.aci_encap_pool:
<<: *aci_pool_present
state: absent
- when: pool_present is changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml
new file mode 100644
index 000000000..1671e252e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_monitoring_policy/tasks/main.yml
@@ -0,0 +1,161 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (akinross@cisco.com)
+
+# 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
+ 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: 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("info") }}'
+ aci_tenant: ansible_test
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when:
+ - query_cloud.current == []
+ block:
+
+ # CLEAN TEST ENVIRONMENT
+
+ - name: Ensure clean tenant configuration
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ state: "{{ item }}"
+ loop:
+ - absent
+ - present
+
+ # TEST CREATE EPG MONITORING POLICY
+
+ - name: Add epg monitoring policy 1 ( check mode )
+ cisco.aci.aci_epg_monitoring_policy: &add_epg_monitoring_policy_1
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ monitoring_policy: monitoring_policy_1
+ state: present
+ check_mode: true
+ register: cm_add_epg_monitoring_policy_1
+
+ - name: Add epg monitoring policy 1
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *add_epg_monitoring_policy_1
+ register: nm_add_epg_monitoring_policy_1
+
+ - name: Add epg monitoring policy 1 again
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *add_epg_monitoring_policy_1
+ register: nm_add_epg_monitoring_policy_1_again
+
+ - name: Verify add epg monitoring policy 1
+ ansible.builtin.assert:
+ that:
+ - cm_add_epg_monitoring_policy_1 is changed
+ - cm_add_epg_monitoring_policy_1.current == []
+ - cm_add_epg_monitoring_policy_1.previous == []
+ - cm_add_epg_monitoring_policy_1.proposed.monEPGPol.attributes.name == "monitoring_policy_1"
+ - nm_add_epg_monitoring_policy_1 is changed
+ - nm_add_epg_monitoring_policy_1.previous == []
+ - nm_add_epg_monitoring_policy_1.current.0.monEPGPol.attributes.name == "monitoring_policy_1"
+ - nm_add_epg_monitoring_policy_1.current.0.monEPGPol.attributes.descr == ""
+ - nm_add_epg_monitoring_policy_1_again is not changed
+ - nm_add_epg_monitoring_policy_1_again.previous.0.monEPGPol.attributes.name == "monitoring_policy_1"
+ - nm_add_epg_monitoring_policy_1_again.previous.0.monEPGPol.attributes.descr == ""
+ - nm_add_epg_monitoring_policy_1_again.current.0.monEPGPol.attributes.name == "monitoring_policy_1"
+ - nm_add_epg_monitoring_policy_1_again.current.0.monEPGPol.attributes.descr == ""
+
+ - name: Change epg monitoring policy 1
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *add_epg_monitoring_policy_1
+ description: "changed description"
+ register: nm_change_epg_monitoring_policy_1
+
+ - name: Verify change epg monitoring policy 1
+ ansible.builtin.assert:
+ that:
+ - nm_change_epg_monitoring_policy_1 is changed
+ - nm_change_epg_monitoring_policy_1.previous.0.monEPGPol.attributes.name == "monitoring_policy_1"
+ - nm_change_epg_monitoring_policy_1.previous.0.monEPGPol.attributes.descr == ""
+ - nm_change_epg_monitoring_policy_1.current.0.monEPGPol.attributes.name == "monitoring_policy_1"
+ - nm_change_epg_monitoring_policy_1.current.0.monEPGPol.attributes.descr == "changed description"
+
+ - name: Add two more epg monitoring policies
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ monitoring_policy: "{{ item }}"
+ state: present
+ loop:
+ - monitoring_policy_2
+ - monitoring_policy_3
+
+ # TEST QUERY EPG MONITORING POLICY
+
+ - name: Query epg monitoring policy 1
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *add_epg_monitoring_policy_1
+ state: query
+ register: query_one
+
+ - name: Query all epg monitoring policies ( class query )
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify query epg monitoring policies
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.monEPGPol.attributes.name == "monitoring_policy_1"
+ - query_all is not changed
+ - query_all.current | length >= 4
+ - query_all.current.0.monEPGPol.attributes.name == "default"
+ - query_all.current.1.monEPGPol.attributes.name == "monitoring_policy_1"
+ - query_all.current.2.monEPGPol.attributes.name == "monitoring_policy_2"
+ - query_all.current.3.monEPGPol.attributes.name == "monitoring_policy_3"
+
+ # TEST REMOVAL EPG MONITORING POLICY
+
+ - name: Remove aepg monitoring policy 1 ( check mode )
+ cisco.aci.aci_epg_monitoring_policy: &remove_epg_monitoring_policy_1
+ <<: *add_epg_monitoring_policy_1
+ state: absent
+ check_mode: true
+ register: cm_remove_epg_monitoring_policy_1
+
+ - name: Remove epg monitoring policy 1
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *remove_epg_monitoring_policy_1
+ register: nm_remove_epg_monitoring_policy_1
+
+ - name: Remove epg monitoring policy 1 again
+ cisco.aci.aci_epg_monitoring_policy:
+ <<: *remove_epg_monitoring_policy_1
+ register: nm_remove_epg_monitoring_policy_1_again
+
+ - name: Verify removal epg monitoring policies
+ ansible.builtin.assert:
+ that:
+ - cm_remove_epg_monitoring_policy_1 is changed
+ - cm_remove_epg_monitoring_policy_1.proposed == {}
+ - nm_remove_epg_monitoring_policy_1 is changed
+ - nm_remove_epg_monitoring_policy_1.previous.0.monEPGPol.attributes.name == "monitoring_policy_1"
+ - nm_remove_epg_monitoring_policy_1.current == []
+ - nm_remove_epg_monitoring_policy_1_again is not changed
+ - nm_remove_epg_monitoring_policy_1_again.previous == []
+ - nm_remove_epg_monitoring_policy_1_again.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml
new file mode 100644
index 000000000..07fb1d304
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_subnet/tasks/main.yml
@@ -0,0 +1,258 @@
+# Test code for the ACI modules
+
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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: ensure tenant does not exists
+ cisco.aci.aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+
+- 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_tenant_absent
+ state: present
+ tenant: ansible_test
+ 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 epg exists for tests to kick off
+ cisco.aci.aci_epg: &aci_epg_present
+ <<: *aci_ap_present
+ epg: anstest
+ register: epg_present
+
+ - name: create subnet - check mode works
+ cisco.aci.aci_epg_subnet: &aci_subnet_present
+ <<: *aci_epg_present
+ state: present
+ subnet_name: anstest
+ gateway: 10.100.100.1
+ mask: 24
+ descr: Ansible Test
+ check_mode: true
+ register: create_check_mode
+
+ - name: create subnet - creation works
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ register: create_subnet
+
+ - name: create new subnet with IpDP_learning disabled - APIC version >= 5.0
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_epg_present
+ state: present
+ descr: Ansible Test
+ gateway: 10.100.101.1
+ mask: 32
+ scope: [private, shared]
+ route_profile: default
+ route_profile_l3out: default
+ subnet_control: no_default_gateway
+ ip_data_plane_learning: disabled
+ register: create_subnet2_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: create new subnet - creation works for APIC version < 5.0
+ cisco.aci.aci_epg_subnet: &aci_subnet2_present
+ <<: *aci_epg_present
+ state: present
+ descr: Ansible Test
+ gateway: 10.100.101.1
+ mask: 32
+ scope: [private, shared]
+ route_profile: default
+ route_profile_l3out: default
+ subnet_control: no_default_gateway
+ register: create_subnet2
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: create subnet again with IpDP_learning disabled - idempotency works for APIC version >= 5
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet2_present
+ ip_data_plane_learning: disabled
+ register: create_idempotency_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: create subnet again - idempotency works for APIC version < 5
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet2_present
+ register: create_idempotency
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: create subnet with bad scope - failure message works
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ scope: [private, public]
+ register: create_bad_scope
+ ignore_errors: true
+
+ - name: create subnet without all necessary params - failure message works
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ epg: "{{ fake_var | default(omit) }}"
+ register: create_incomplete_data
+ ignore_errors: true
+
+ - name: create subnet without valid mask - failure message works
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ mask: 130
+ register: create_wrong_mask
+ ignore_errors: true
+
+ - name: asserts for subnet creation tasks
+ assert:
+ that:
+ - create_check_mode is changed
+ - create_check_mode.sent.fvSubnet.attributes.descr == create_subnet.sent.fvSubnet.attributes.descr == 'Ansible Test'
+ - create_check_mode.sent.fvSubnet.attributes.ip == create_subnet.sent.fvSubnet.attributes.ip == '10.100.100.1/24'
+ - create_check_mode.sent.fvSubnet.attributes.name == create_subnet.sent.fvSubnet.attributes.name == 'anstest'
+ - create_subnet is changed
+ - create_subnet.current.0.fvSubnet.attributes.annotation == 'orchestrator:ansible'
+ - create_subnet.previous == []
+ - create_bad_scope is failed
+ - create_bad_scope.msg.startswith("Parameter 'scope' cannot be both 'private' and 'public'")
+ - create_incomplete_data is failed
+ - 'create_incomplete_data.msg == "state is present but all of the following are missing: epg"'
+ - create_wrong_mask is failed
+ - create_wrong_mask.msg == "Valid Subnet Masks are 0 to 32 for IPv4 Addresses and 0 to 128 for IPv6 addresses"
+
+ - name: assert for subnet IpDPlearning tasks version >=5
+ assert:
+ that:
+ - create_subnet2_5 is changed
+ - create_subnet2_5.current.0.fvSubnet.attributes.ctrl == 'no-default-gateway'
+ - create_subnet2_5.sent == create_subnet2_5.proposed
+ - create_subnet2_5.sent.fvSubnet.attributes.scope == "private,shared"
+ - create_subnet2_5.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnL3extOutName == 'default'
+ - create_subnet2_5.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnRtctrlProfileName == 'default'
+ - create_idempotency_5 is not changed
+ - create_idempotency_5.previous != []
+ - create_subnet.current.0.fvSubnet.attributes.ipDPLearning == 'enabled'
+ - create_subnet2_5.current.0.fvSubnet.attributes.ipDPLearning == 'disabled'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: assert for subnet IpDPlearning tasks version < 5
+ assert:
+ that:
+ - create_subnet2 is changed
+ - create_subnet2.current.0.fvSubnet.attributes.ctrl == 'no-default-gateway'
+ - create_subnet2.sent == create_subnet2.proposed
+ - create_subnet2.sent.fvSubnet.attributes.scope == "private,shared"
+ - create_subnet2.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnL3extOutName == 'default'
+ - create_subnet2.sent.fvSubnet.children.0.fvRsBDSubnetToProfile.attributes.tnRtctrlProfileName == 'default'
+ - create_idempotency is not changed
+ - create_idempotency.previous != []
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: get all in epg
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_epg_present
+ state: query
+ register: get_all_epg
+
+ - name: get specific subnet
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ state: query
+ register: get_subnet
+
+ - name: get all subnets matching gateway
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ state: query
+ tenant: "{{ fake_var | default(omit) }}"
+ ap: "{{ fake_var | default(omit) }}"
+ epg: "{{ fake_var | default(omit) }}"
+ register: get_subnets_gateway
+
+ - name: asserts for query tasks
+ assert:
+ that:
+ - get_all_epg is not changed
+ - '"rsp-subtree-class=fvRsBDSubnetToProfile,fvRsNdPfxPol,fvSubnet" in get_all_epg.filter_string'
+ - '"tn-ansible_test/ap-anstest/epg-anstest.json" in get_all_epg.url'
+ - get_subnet is not changed
+ - get_subnet.current | length == 1
+ - '"tn-ansible_test/ap-anstest/epg-anstest/subnet-[10.100.100.1/24].json" in get_subnet.url'
+ - get_subnets_gateway is not changed
+ - '"query-target-filter=eq(fvSubnet.ip,\"10.100.100.1/24\")" in get_subnets_gateway.filter_string'
+ - '"class/fvSubnet.json" in get_subnets_gateway.url'
+
+ - name: delete subnet - check mode works
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ state: absent
+ check_mode: true
+ register: delete_check_mode
+
+ - name: delete subnet - delete works
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet_present
+ state: absent
+ register: delete_subnet
+
+ - name: delete subnet - cleanup
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet2_present
+ state: absent
+
+ - name: delete subnet again - idempotency works
+ cisco.aci.aci_epg_subnet:
+ <<: *aci_subnet2_present
+ state: absent
+ register: delete_idempotency
+
+ - name: asserts for deletion task
+ assert:
+ that:
+ - delete_check_mode is changed
+ - delete_check_mode.proposed == {}
+ - delete_subnet is changed
+ - delete_subnet.previous != []
+ - delete_subnet.method == "DELETE"
+ - delete_idempotency is not changed
+ - delete_idempotency.previous == []
+
+ - name: delete tenant - cleanup before ending tests
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present is changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml
new file mode 100644
index 000000000..9f871da6b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_interface_policy_group/tasks/main.yml
@@ -0,0 +1,346 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Sabari Jaganathan (@sajagana)
+
+# 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
+
+# SET VARS
+- 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: Query system information
+ cisco.aci.aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Ensure leaf_policy_group does not exist
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ name: leaf_policy_group
+ type: leaf
+ state: absent
+
+- name: Ensure spine_policy_group does not exist
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ name: spine_policy_group
+ type: spine
+ state: absent
+
+- name: Add a leaf fabric interface policy group with check mode
+ aci_fabric_interface_policy_group: &cm_leaf_policy_group_present
+ <<: *aci_info
+ name: leaf_policy_group
+ type: leaf
+ descr: leaf_policy_group created
+ state: present
+ check_mode: true
+ register: cm_leaf_policy_group_present
+
+- name: Add a leaf fabric interface policy group with normal mode
+ aci_fabric_interface_policy_group: &nm_leaf_policy_group_present
+ <<: *cm_leaf_policy_group_present
+ dwdm_policy: default
+ link_level_policy: default
+ link_flap_policy: default
+ l3_interface_policy: default
+ macsec_policy: default
+ monitoring_policy: default
+ register: nm_leaf_policy_group_present
+
+- name: Add a leaf fabric interface policy group with normal mode again
+ aci_fabric_interface_policy_group:
+ <<: *nm_leaf_policy_group_present
+ register: nm_leaf_policy_group_present_again
+
+- name: Add a spine fabric interface policy group with check mode
+ aci_fabric_interface_policy_group: &cm_spine_policy_group_present
+ <<: *aci_info
+ name: spine_policy_group
+ type: spine
+ descr: spine_policy_group created
+ dwdm_policy: default
+ link_level_policy: default
+ link_flap_policy: default
+ l3_interface_policy: default
+ macsec_policy: default
+ monitoring_policy: default
+ state: present
+ check_mode: true
+ register: cm_spine_policy_group_present
+
+- name: Execute tasks only for ACI v6.0(2h)+
+ when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=')
+ block:
+ - name: Add a spine fabric interface policy group with transceiver_policy_tdn
+ aci_fabric_interface_policy_group: &tp_spine_policy_group_present
+ <<: *aci_info
+ name: spine_policy_group
+ type: spine
+ descr: spine_policy_group created
+ transceiver_policy_tdn: "uni/fabric/zrfab-default"
+ state: present
+ register: tp_spine_policy_group_present
+
+ - name: Remove the transceiver_policy from the spine fabric interface policy group
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ name: spine_policy_group
+ type: spine
+ descr: spine_policy_group created
+ transceiver_policy_tdn: ""
+ state: present
+ register: tp_spine_policy_group_absent
+
+ - name: Assertions check for add fabric interface policy groups
+ assert:
+ that:
+ - tp_spine_policy_group_present is changed
+ - tp_spine_policy_group_absent is changed
+ - tp_spine_policy_group_present.current.0.fabricSpPortPGrp.children | selectattr('fabricRsOpticsFabIfPol.attributes.tDn', 'defined') | selectattr('fabricRsOpticsFabIfPol.attributes.tDn', 'equalto', "uni/fabric/zrfab-default")
+ - tp_spine_policy_group_absent.current.0.fabricSpPortPGrp.children | selectattr('fabricRsOpticsFabIfPol.attributes.tDn', 'defined') | selectattr('fabricRsOpticsFabIfPol.attributes.tDn', 'equalto', "")
+
+- name: Add a spine fabric interface policy group with normal mode
+ aci_fabric_interface_policy_group:
+ <<: *cm_spine_policy_group_present
+ register: nm_spine_policy_group_present
+
+- name: Add a spine fabric interface policy group with normal mode again
+ aci_fabric_interface_policy_group:
+ <<: *cm_spine_policy_group_present
+ register: nm_spine_policy_group_present_again
+
+- name: Update a spine fabric interface policy group with check mode
+ aci_fabric_interface_policy_group: &cm_spine_policy_group_update
+ <<: *cm_spine_policy_group_present
+ descr: spine_policy_group updated
+ dwdm_policy: ""
+ link_level_policy: ""
+ link_flap_policy: ""
+ l3_interface_policy: ""
+ macsec_policy: ""
+ monitoring_policy: ""
+ check_mode: true
+ register: cm_spine_policy_group_update
+
+- name: Update a spine fabric interface policy group with normal mode
+ aci_fabric_interface_policy_group:
+ <<: *cm_spine_policy_group_update
+ register: nm_spine_policy_group_update
+
+- name: Update a spine fabric interface policy group with normal mode again
+ aci_fabric_interface_policy_group:
+ <<: *cm_spine_policy_group_update
+ register: nm_spine_policy_group_update_again
+
+- name: Assertions check for add fabric interface policy groups
+ assert:
+ that:
+ - cm_leaf_policy_group_present is changed
+ - cm_leaf_policy_group_present.current == []
+ - cm_leaf_policy_group_present.previous == []
+ - cm_leaf_policy_group_present.mo.fabricLePortPGrp.attributes.name == "leaf_policy_group"
+ - cm_leaf_policy_group_present.mo.fabricLePortPGrp.attributes.descr == "leaf_policy_group created"
+ - nm_leaf_policy_group_present is changed
+ - nm_leaf_policy_group_present.current != []
+ - nm_leaf_policy_group_present.previous == []
+ - nm_leaf_policy_group_present.current.0.fabricLePortPGrp.attributes.name == "leaf_policy_group"
+ - nm_leaf_policy_group_present.current.0.fabricLePortPGrp.attributes.descr == "leaf_policy_group created"
+ - nm_leaf_policy_group_present.current.0.fabricLePortPGrp.attributes.dn == "uni/fabric/funcprof/leportgrp-leaf_policy_group"
+ - nm_leaf_policy_group_present.current.0.fabricLePortPGrp.children | length >= 6
+ - nm_leaf_policy_group_present_again is not changed
+ - nm_leaf_policy_group_present_again.current != []
+ - nm_leaf_policy_group_present_again.previous != []
+ - nm_leaf_policy_group_present_again.current.0.fabricLePortPGrp.attributes.name == nm_leaf_policy_group_present_again.previous.0.fabricLePortPGrp.attributes.name == "leaf_policy_group"
+ - nm_leaf_policy_group_present_again.current.0.fabricLePortPGrp.attributes.descr == nm_leaf_policy_group_present_again.previous.0.fabricLePortPGrp.attributes.descr == "leaf_policy_group created"
+ - nm_leaf_policy_group_present_again.current.0.fabricLePortPGrp.attributes.dn == nm_leaf_policy_group_present_again.previous.0.fabricLePortPGrp.attributes.dn == "uni/fabric/funcprof/leportgrp-leaf_policy_group"
+ - cm_spine_policy_group_present is changed
+ - cm_spine_policy_group_present.current == []
+ - cm_spine_policy_group_present.previous == []
+ - cm_spine_policy_group_present.mo.fabricSpPortPGrp.attributes.name == "spine_policy_group"
+ - cm_spine_policy_group_present.mo.fabricSpPortPGrp.attributes.descr == "spine_policy_group created"
+ - nm_spine_policy_group_present is changed
+ - nm_spine_policy_group_present.current != []
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.attributes.name == "spine_policy_group"
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group created"
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.attributes.dn == "uni/fabric/funcprof/spportgrp-spine_policy_group"
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.children | length >= 6
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.children | selectattr('fabricRsDwdmFabIfPol.attributes.tnDwdmFabIfPolName', 'defined') | selectattr('fabricRsDwdmFabIfPol.attributes.tnDwdmFabIfPolName', 'equalto', "default")
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.children | selectattr('fabricRsFIfPol.attributes.tnFabricFIfPolName', 'defined') | selectattr('fabricRsFIfPol.attributes.tnFabricFIfPolName', 'equalto', "default")
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.children | selectattr('fabricRsFLinkFlapPol.attributes.tnFabricFLinkFlapPolName', 'defined') | selectattr('fabricRsFLinkFlapPol.attributes.tnFabricFLinkFlapPolName', 'equalto', "default")
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.children | selectattr('fabricRsL3IfPol.attributes.tnL3IfPolName', 'defined') | selectattr('fabricRsL3IfPol.attributes.tnL3IfPolName', 'equalto', "default")
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.children | selectattr('fabricRsMacsecFabIfPol.attributes.tnMacsecFabIfPolName', 'defined') | selectattr('fabricRsMacsecFabIfPol.attributes.tnMacsecFabIfPolName', 'equalto', "default")
+ - nm_spine_policy_group_present.current.0.fabricSpPortPGrp.children | selectattr('fabricRsMonIfFabricPol.attributes.tnMonFabricPolName', 'defined') | selectattr('fabricRsMonIfFabricPol.attributes.tnMonFabricPolName', 'equalto', "default")
+ - nm_spine_policy_group_present_again is not changed
+ - nm_spine_policy_group_present_again.current != []
+ - nm_spine_policy_group_present_again.previous != []
+ - nm_spine_policy_group_present_again.current.0.fabricSpPortPGrp.attributes.name == nm_spine_policy_group_present_again.previous.0.fabricSpPortPGrp.attributes.name == "spine_policy_group"
+ - nm_spine_policy_group_present_again.current.0.fabricSpPortPGrp.attributes.descr == nm_spine_policy_group_present_again.previous.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group created"
+ - nm_spine_policy_group_present_again.current.0.fabricSpPortPGrp.attributes.dn == nm_spine_policy_group_present_again.previous.0.fabricSpPortPGrp.attributes.dn == "uni/fabric/funcprof/spportgrp-spine_policy_group"
+ - cm_spine_policy_group_update is changed
+ - cm_spine_policy_group_update.previous.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group created"
+ - cm_spine_policy_group_update.current.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group created"
+ - nm_spine_policy_group_update is changed
+ - nm_spine_policy_group_update.previous.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group created"
+ - nm_spine_policy_group_update.current.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group updated"
+ - nm_spine_policy_group_update.previous.0.fabricSpPortPGrp.children | selectattr('fabricRsDwdmFabIfPol.attributes.tnDwdmFabIfPolName', 'defined') | selectattr('fabricRsDwdmFabIfPol.attributes.tnDwdmFabIfPolName', 'equalto', "default")
+ - nm_spine_policy_group_update.previous.0.fabricSpPortPGrp.children | selectattr('fabricRsFIfPol.attributes.tnFabricFIfPolName', 'defined') | selectattr('fabricRsFIfPol.attributes.tnFabricFIfPolName', 'equalto', "default")
+ - nm_spine_policy_group_update.previous.0.fabricSpPortPGrp.children | selectattr('fabricRsFLinkFlapPol.attributes.tnFabricFLinkFlapPolName', 'defined') | selectattr('fabricRsFLinkFlapPol.attributes.tnFabricFLinkFlapPolName', 'equalto', "default")
+ - nm_spine_policy_group_update.previous.0.fabricSpPortPGrp.children | selectattr('fabricRsL3IfPol.attributes.tnL3IfPolName', 'defined') | selectattr('fabricRsL3IfPol.attributes.tnL3IfPolName', 'equalto', "default")
+ - nm_spine_policy_group_update.previous.0.fabricSpPortPGrp.children | selectattr('fabricRsMacsecFabIfPol.attributes.tnMacsecFabIfPolName', 'defined') | selectattr('fabricRsMacsecFabIfPol.attributes.tnMacsecFabIfPolName', 'equalto', "default")
+ - nm_spine_policy_group_update.previous.0.fabricSpPortPGrp.children | selectattr('fabricRsMonIfFabricPol.attributes.tnMonFabricPolName', 'defined') | selectattr('fabricRsMonIfFabricPol.attributes.tnMonFabricPolName', 'equalto', "default")
+ - nm_spine_policy_group_update.current.0.fabricSpPortPGrp.children | selectattr('fabricRsDwdmFabIfPol.attributes.tnDwdmFabIfPolName', 'defined') | selectattr('fabricRsDwdmFabIfPol.attributes.tnDwdmFabIfPolName', 'equalto', "")
+ - nm_spine_policy_group_update.current.0.fabricSpPortPGrp.children | selectattr('fabricRsFIfPol.attributes.tnFabricFIfPolName', 'defined') | selectattr('fabricRsFIfPol.attributes.tnFabricFIfPolName', 'equalto', "")
+ - nm_spine_policy_group_update.current.0.fabricSpPortPGrp.children | selectattr('fabricRsFLinkFlapPol.attributes.tnFabricFLinkFlapPolName', 'defined') | selectattr('fabricRsFLinkFlapPol.attributes.tnFabricFLinkFlapPolName', 'equalto', "")
+ - nm_spine_policy_group_update.current.0.fabricSpPortPGrp.children | selectattr('fabricRsL3IfPol.attributes.tnL3IfPolName', 'defined') | selectattr('fabricRsL3IfPol.attributes.tnL3IfPolName', 'equalto', "")
+ - nm_spine_policy_group_update.current.0.fabricSpPortPGrp.children | selectattr('fabricRsMacsecFabIfPol.attributes.tnMacsecFabIfPolName', 'defined') | selectattr('fabricRsMacsecFabIfPol.attributes.tnMacsecFabIfPolName', 'equalto', "")
+ - nm_spine_policy_group_update.current.0.fabricSpPortPGrp.children | selectattr('fabricRsMonIfFabricPol.attributes.tnMonFabricPolName', 'defined') | selectattr('fabricRsMonIfFabricPol.attributes.tnMonFabricPolName', 'equalto', "")
+ - nm_spine_policy_group_update_again is not changed
+ - nm_spine_policy_group_update_again.previous.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group updated"
+ - nm_spine_policy_group_update_again.current.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group updated"
+
+- name: Invalid test - add a fabric interface policy group without type
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ name: nt_spine_policy_group
+ descr: negative test nt_spine_policy_group
+ state: present
+ register: nt_without_type
+ ignore_errors: true
+
+- name: Invalid test - add a fabric interface policy group without name
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ type: spine
+ descr: negative test spine_policy_group
+ state: present
+ register: nt_without_name
+ ignore_errors: true
+
+- name: Assertions check for invalid test - add fabric interface policy groups
+ assert:
+ that:
+ - nt_without_type is not changed
+ - nt_without_type.msg == "missing required arguments{{':'}} type"
+ - nt_without_name is not changed
+ - nt_without_name.msg == "state is present but all of the following are missing{{':'}} name"
+
+- name: Query a leaf fabric interface policy group with name
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ name: leaf_policy_group
+ type: leaf
+ state: query
+ register: query_leaf_policy_group
+
+- name: Query all leaf fabric interface policy groups
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ type: leaf
+ state: query
+ register: query_all_leaf_policy_group
+
+- name: Query a spine fabric interface policy group with name
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ name: spine_policy_group
+ type: spine
+ state: query
+ register: query_a_spine_policy_group
+
+- name: Query all spine fabric interface policy groups
+ aci_fabric_interface_policy_group:
+ <<: *aci_info
+ type: spine
+ state: query
+ register: query_all_spine_policy_group
+
+- name: Assertions check for query a fabric interface policy groups
+ assert:
+ that:
+ - query_leaf_policy_group is not changed
+ - query_leaf_policy_group.current != []
+ - query_leaf_policy_group.current.0.fabricLePortPGrp.attributes.name == "leaf_policy_group"
+ - query_leaf_policy_group.current.0.fabricLePortPGrp.attributes.dn == "uni/fabric/funcprof/leportgrp-leaf_policy_group"
+ - query_leaf_policy_group.current.0.fabricLePortPGrp.attributes.descr == "leaf_policy_group created"
+ - query_all_leaf_policy_group is not changed
+ - query_all_leaf_policy_group.current != []
+ - query_all_leaf_policy_group.current | length >= 1
+ - query_a_spine_policy_group is not changed
+ - query_a_spine_policy_group.current != []
+ - query_a_spine_policy_group.current.0.fabricSpPortPGrp.attributes.name == "spine_policy_group"
+ - query_a_spine_policy_group.current.0.fabricSpPortPGrp.attributes.dn == "uni/fabric/funcprof/spportgrp-spine_policy_group"
+ - query_a_spine_policy_group.current.0.fabricSpPortPGrp.attributes.descr == "spine_policy_group updated"
+ - query_all_spine_policy_group is not changed
+ - query_all_spine_policy_group.current != []
+ - query_all_spine_policy_group.current | length >= 1
+
+- name: Remove a leaf fabric interface policy group with check mode
+ aci_fabric_interface_policy_group: &cm_leaf_policy_group_absent
+ <<: *cm_leaf_policy_group_present
+ state: absent
+ check_mode: true
+ register: cm_leaf_policy_group_absent
+
+- name: Remove a leaf fabric interface policy group with normal mode
+ aci_fabric_interface_policy_group:
+ <<: *cm_leaf_policy_group_absent
+ register: nm_leaf_policy_group_absent
+
+- name: Remove a leaf fabric interface policy group with normal mode again
+ aci_fabric_interface_policy_group:
+ <<: *cm_leaf_policy_group_absent
+ register: nm_leaf_policy_group_absent_again
+
+- name: Remove a spine fabric interface policy group with check mode
+ aci_fabric_interface_policy_group: &cm_spine_policy_group_absent
+ <<: *cm_spine_policy_group_present
+ state: absent
+ check_mode: true
+ register: cm_spine_policy_group_absent
+
+- name: Remove a spine fabric interface policy group with normal mode
+ aci_fabric_interface_policy_group:
+ <<: *cm_spine_policy_group_absent
+ register: nm_spine_policy_group_absent
+
+- name: Remove a spine fabric interface policy group with normal mode again
+ aci_fabric_interface_policy_group:
+ <<: *cm_spine_policy_group_absent
+ register: nm_spine_policy_group_absent_again
+
+- name: Assertions check for remove a fabric interface policy groups
+ assert:
+ that:
+ - cm_leaf_policy_group_absent is changed
+ - cm_leaf_policy_group_absent.current != []
+ - cm_leaf_policy_group_absent.previous != []
+ - nm_leaf_policy_group_absent is changed
+ - nm_leaf_policy_group_absent.current == []
+ - nm_leaf_policy_group_absent.previous != []
+ - nm_leaf_policy_group_absent_again is not changed
+ - nm_leaf_policy_group_absent_again.current == []
+ - nm_leaf_policy_group_absent_again.previous == []
+ - cm_spine_policy_group_absent is changed
+ - cm_spine_policy_group_absent.current != []
+ - cm_spine_policy_group_absent.previous != []
+ - nm_spine_policy_group_absent is changed
+ - nm_spine_policy_group_absent.current == []
+ - nm_spine_policy_group_absent.previous != []
+ - nm_spine_policy_group_absent_again is not changed
+ - nm_spine_policy_group_absent_again.current == []
+ - nm_spine_policy_group_absent_again.previous == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml
index 36e065e5b..552661556 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml
@@ -1,5 +1,6 @@
# Test code for the ACI modules
# Copyright: (c) 2017, Bruno Calogero <brunocalogero@hotmail.com>
+# Copyright: (c) 2023, Gaspard Micol <gmicol@cisco.com>
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -8,38 +9,52 @@
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") }}'
# CLEAN ENVIRONMENT
- name: Remove fabric node
cisco.aci.aci_fabric_node: &aci_fabric_node_absent
- 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") }}'
+ <<: *aci_info
serial: ansible_test
node_id: 105
state: absent
+- name: Remove fabric node 2
+ cisco.aci.aci_fabric_node: &aci_fabric_node_absent_2
+ <<: *aci_info
+ serial: ansible_test_2
+ node_id: 106
+ state: absent
# ADD FABRIC NODE
-- name: Add fabric node (check_mode)
+- name: Add fabric node with tier-2 leaf (check_mode)
cisco.aci.aci_fabric_node: &aci_fabric_node_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
- serial: ansible_test
- node_id: 105
+ <<: *aci_fabric_node_absent
switch: anstest
+ role: leaf
+ node_type: tier_2
state: present
check_mode: true
- register: cm_add_fabric_node
+ register: cm_add_fabric_node_tier_2
+
+- name: Add fabric node with remote leaf
+ cisco.aci.aci_fabric_node: &aci_fabric_node_present_2
+ <<: *aci_fabric_node_absent_2
+ switch: anstest_2
+ role: leaf
+ node_type: remote
+ remote_leaf_pool_id: 2
+ state: present
+ register: nm_add_fabric_node_remote
- name: Add fabric node (normal mode)
cisco.aci.aci_fabric_node: *aci_fabric_node_present
@@ -54,15 +69,44 @@
cisco.aci.aci_fabric_node: *aci_fabric_node_present
register: nm_add_fabric_node_again
+- name: test error - mutually exclusive attributes
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_present_2
+ node_type: tier_2
+ register: test_error_mutually_exclusive
+ ignore_errors: true
+
+- name: test error - check failure when changing node type
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_present
+ node_type: virtual
+ register: test_error_change__node_type
+ ignore_errors: true
+
+- name: test error - check failure when changing Pool Id
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_present_2
+ remote_leaf_pool_id: 3
+ register: test_error_change_Pool_Id
+ ignore_errors: true
+
- name: Verify add_fabric_node
assert:
that:
- - cm_add_fabric_node is changed
+ - cm_add_fabric_node_tier_2 is changed
- nm_add_fabric_node is changed
- nm_add_fabric_node.current.0.fabricNodeIdentP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_fabric_node.current.0.fabricNodeIdentP.attributes.role == 'leaf'
+ - nm_add_fabric_node.current.0.fabricNodeIdentP.attributes.nodeType == 'tier-2-leaf'
+ - nm_add_fabric_node_remote is changed
+ - nm_add_fabric_node_remote.current.0.fabricNodeIdentP.attributes.nodeType == 'remote-leaf-wan'
+ - nm_add_fabric_node_remote.current.0.fabricNodeIdentP.attributes.extPoolId == '2'
# FIXME: Module is not idempotent
- cm_add_fabric_node_again is not changed
- nm_add_fabric_node_again is not changed
+ - test_error_mutually_exclusive.msg == "External Pool Id is not compatible with a node type other than 'remote'."
+ - test_error_change__node_type.error.text == "Create-only and naming props cannot be modified after creation, class=fabricNodeIdentP, prop=nodeType"
+ - test_error_change_Pool_Id.error.text == "Create-only and naming props cannot be modified after creation, class=fabricNodeIdentP, prop=extPoolId"
# CHANGE FABRIC NODE
@@ -150,7 +194,7 @@
- name: Query our fabric_node
cisco.aci.aci_fabric_node:
<<: *aci_fabric_node_query
- serial: ansible_test # might need node_id too
+ serial: ansible_test
check_mode: true
register: cm_query_fabric_node
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml
new file mode 100644
index 000000000..f41c69150
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node_control/tasks/main.yml
@@ -0,0 +1,179 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Tim Cragg (@timcragg)
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN ENVIRONMENT
+- name: Pre-Test Clean Environment of Fabric Node Controls
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_info
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - ansible_fabric_node_control_1
+ - ansible_fabric_node_control_2
+ - ansible_fabric_node_control_3
+
+# CREATE FABRIC NODE CONTROL
+- name: Create Fabric Node Control (check mode)
+ cisco.aci.aci_fabric_node_control: &aci_fabric_node_control
+ <<: *aci_info
+ name: ansible_fabric_node_control_1
+ check_mode: true
+ register: cm_create_fabric_node_control
+
+- name: Create Fabric Node Control (normal mode)
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_fabric_node_control
+ register: nm_create_fabric_node_control
+
+- name: Create Fabric Node Control again
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_fabric_node_control
+ register: nm_create_fabric_node_control_again
+
+- name: Verify Fabric Node Control creation
+ ansible.builtin.assert:
+ that:
+ - cm_create_fabric_node_control is changed
+ - cm_create_fabric_node_control.current == []
+ - cm_create_fabric_node_control.previous == []
+ - cm_create_fabric_node_control.proposed.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+ - nm_create_fabric_node_control is changed
+ - nm_create_fabric_node_control.previous == []
+ - nm_create_fabric_node_control.current.0.fabricNodeControl.attributes.control == ""
+ - nm_create_fabric_node_control.current.0.fabricNodeControl.attributes.descr == ""
+ - nm_create_fabric_node_control.current.0.fabricNodeControl.attributes.featureSel == "telemetry"
+ - nm_create_fabric_node_control.current.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+ - nm_create_fabric_node_control_again is not changed
+ - nm_create_fabric_node_control_again.current.0.fabricNodeControl.attributes.control == ""
+ - nm_create_fabric_node_control_again.current.0.fabricNodeControl.attributes.descr == ""
+ - nm_create_fabric_node_control_again.current.0.fabricNodeControl.attributes.featureSel == "telemetry"
+ - nm_create_fabric_node_control_again.current.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+ - nm_create_fabric_node_control_again.previous.0.fabricNodeControl.attributes.control == ""
+ - nm_create_fabric_node_control_again.previous.0.fabricNodeControl.attributes.descr == ""
+ - nm_create_fabric_node_control_again.previous.0.fabricNodeControl.attributes.featureSel == "telemetry"
+ - nm_create_fabric_node_control_again.previous.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+
+# UPDATE FABRIC NODE CONTROL
+- name: Update Fabric Node Control
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_fabric_node_control
+ description: Updated Ansible Test Fabric Node Control
+ enable_dom: true
+ feature_selection: analytics
+ register: update_fabric_node_control
+
+- name: Verify Fabric Node Control update
+ ansible.builtin.assert:
+ that:
+ - update_fabric_node_control is changed
+ - update_fabric_node_control.current.0.fabricNodeControl.attributes.control == "Dom"
+ - update_fabric_node_control.current.0.fabricNodeControl.attributes.descr == "Updated Ansible Test Fabric Node Control"
+ - update_fabric_node_control.current.0.fabricNodeControl.attributes.featureSel == "analytics"
+ - update_fabric_node_control.current.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+ - update_fabric_node_control.previous.0.fabricNodeControl.attributes.control == ""
+ - update_fabric_node_control.previous.0.fabricNodeControl.attributes.descr == ""
+ - update_fabric_node_control.previous.0.fabricNodeControl.attributes.featureSel == "telemetry"
+ - update_fabric_node_control.previous.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+
+# QUERY FABRIC NODE CONTROL
+- name: Create another Fabric Node Control
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_info
+ name: "{{ item }}"
+ feature_selection: netflow
+ loop:
+ - ansible_fabric_node_control_2
+ - ansible_fabric_node_control_3
+
+- name: Query a Fabric Node Control
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_fabric_node_control
+ state: query
+ register: query_one
+
+- name: Query all Fabric Node Controls
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify Fabric Node Control queries
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.fabricNodeControl.attributes.control == "Dom"
+ - query_one.current.0.fabricNodeControl.attributes.descr == "Updated Ansible Test Fabric Node Control"
+ - query_one.current.0.fabricNodeControl.attributes.featureSel == "analytics"
+ - query_one.current.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+ - query_all is not changed
+ - query_all.current | length > 3
+
+# REMOVE FABRIC NODE CONTROL
+- name: Remove Fabric Node Control (check mode)
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_fabric_node_control
+ state: absent
+ register: cm_remove_fabric_node_control
+ check_mode: true
+
+- name: Remove Fabric Node Control
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_fabric_node_control
+ state: absent
+ register: nm_remove_fabric_node_control
+
+- name: Remove Fabric Node Control again
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_fabric_node_control
+ state: absent
+ register: nm__remove_fabric_node_control_again
+
+- name: Verify Fabric Node Control removal
+ ansible.builtin.assert:
+ that:
+ - cm_remove_fabric_node_control is changed
+ - cm_remove_fabric_node_control.proposed == {}
+ - cm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.control == "Dom"
+ - cm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.descr == "Updated Ansible Test Fabric Node Control"
+ - cm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.featureSel == "analytics"
+ - cm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+ - nm_remove_fabric_node_control is changed
+ - nm_remove_fabric_node_control.current == []
+ - nm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.control == "Dom"
+ - nm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.descr == "Updated Ansible Test Fabric Node Control"
+ - nm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.featureSel == "analytics"
+ - nm_remove_fabric_node_control.previous.0.fabricNodeControl.attributes.name == "ansible_fabric_node_control_1"
+ - nm__remove_fabric_node_control_again is not changed
+ - nm__remove_fabric_node_control_again.current == []
+ - nm__remove_fabric_node_control_again.previous == []
+
+# CLEAN ENVIRONMENT
+- name: PPost-Test Clean Environment of Fabric Node Controls
+ cisco.aci.aci_fabric_node_control:
+ <<: *aci_info
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - ansible_fabric_node_control_1
+ - ansible_fabric_node_control_2
+ - ansible_fabric_node_control_3
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml
new file mode 100644
index 000000000..ca9fb8209
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_selector/tasks/main.yml
@@ -0,0 +1,305 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Tim Cragg (@timcragg)
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN EXISTING ENVIRONMENT
+- name: Ensure Fabric Pod Selectors are absent before testing
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *aci_info
+ name: "{{ item.name }}"
+ pod_profile: default
+ type: "{{ item.type }}"
+ state: absent
+ loop:
+ - {name: ansible_fabric_pod_pol_sel_1, type: all}
+ - {name: ansible_fabric_pod_pol_sel_2, type: range}
+ - {name: ansible_fabric_pod_pol_sel_3, type: range}
+ - {name: default, type: all}
+
+- name: Ensure a Pod Policy Group exists before testing
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_pod_pol_grp_1
+
+# CREATE FABRIC POD SELECTOR TYPE ALL
+- name: Create Fabric Pod Selector without blocks (check mode)
+ cisco.aci.aci_fabric_pod_selector: &fabric_pod_sel_without_blocks
+ <<: *aci_info
+ name: ansible_fabric_pod_pol_sel_1
+ type: all
+ pod_profile: default
+ description: Created Ansible Pod Selector
+ check_mode: true
+ register: cm_create_fabric_pod_sel_without_blocks
+
+- name: Create Fabric Pod Selector without blocks
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_without_blocks
+ register: nm_create_fabric_pod_sel_without_blocks
+
+- name: Create Fabric Pod Selector without blocks again
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_without_blocks
+ register: nm_create_fabric_pod_sel_without_blocks_again
+
+- name: Verify create of Pod Selector
+ ansible.builtin.assert:
+ that:
+ - cm_create_fabric_pod_sel_without_blocks is changed
+ - cm_create_fabric_pod_sel_without_blocks.current == []
+ - cm_create_fabric_pod_sel_without_blocks.previous == []
+ - cm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - cm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - cm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - cm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - cm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.type == "ALL"
+ - nm_create_fabric_pod_sel_without_blocks is changed
+ - nm_create_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_create_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_create_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - nm_create_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - nm_create_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.type == "ALL"
+ - nm_create_fabric_pod_sel_without_blocks.previous == []
+ - nm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - nm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - nm_create_fabric_pod_sel_without_blocks.proposed.fabricPodS.attributes.type == "ALL"
+ - nm_create_fabric_pod_sel_without_blocks_again is not changed
+ - nm_create_fabric_pod_sel_without_blocks_again.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_create_fabric_pod_sel_without_blocks_again.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_create_fabric_pod_sel_without_blocks_again.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - nm_create_fabric_pod_sel_without_blocks_again.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - nm_create_fabric_pod_sel_without_blocks_again.current.0.fabricPodS.attributes.type == "ALL"
+ - nm_create_fabric_pod_sel_without_blocks_again.previous.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_create_fabric_pod_sel_without_blocks_again.previous.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_create_fabric_pod_sel_without_blocks_again.previous.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - nm_create_fabric_pod_sel_without_blocks_again.previous.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - nm_create_fabric_pod_sel_without_blocks_again.previous.0.fabricPodS.attributes.type == "ALL"
+
+# REMOVE FABRIC POD SELECTOR
+- name: Remove Fabric Pod Selector without blocks (check mode)
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_without_blocks
+ state: absent
+ check_mode: true
+ register: cm_remove_fabric_pod_sel_without_blocks
+
+- name: Remove Fabric Pod Selector without blocks
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_without_blocks
+ state: absent
+ register: nm_remove_fabric_pod_sel_without_blocks
+
+- name: Remove Fabric Pod Selector without blocks again
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_without_blocks
+ state: absent
+ register: nm_remove_fabric_pod_sel_without_blocks_again
+
+- name: Verify removal of Pod Selector
+ ansible.builtin.assert:
+ that:
+ - cm_remove_fabric_pod_sel_without_blocks is changed
+ - cm_remove_fabric_pod_sel_without_blocks.proposed == {}
+ - cm_remove_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - cm_remove_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - cm_remove_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - cm_remove_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - cm_remove_fabric_pod_sel_without_blocks.current.0.fabricPodS.attributes.type == "ALL"
+ - cm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - cm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - cm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - cm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - cm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.type == "ALL"
+ - nm_remove_fabric_pod_sel_without_blocks is changed
+ - nm_remove_fabric_pod_sel_without_blocks.proposed == {}
+ - nm_remove_fabric_pod_sel_without_blocks.current == []
+ - nm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_1-typ-ALL"
+ - nm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_1"
+ - nm_remove_fabric_pod_sel_without_blocks.previous.0.fabricPodS.attributes.type == "ALL"
+ - nm_remove_fabric_pod_sel_without_blocks_again is not changed
+ - nm_remove_fabric_pod_sel_without_blocks_again.current == []
+ - nm_remove_fabric_pod_sel_without_blocks_again.previous == []
+
+# CREATE & UPDATE FABRIC POD SELECTOR TYPE RANGE
+- name: Create Fabric Pod Selector with blocks and policy
+ cisco.aci.aci_fabric_pod_selector: &fabric_pod_sel_blocks
+ <<: *fabric_pod_sel_without_blocks
+ name: ansible_fabric_pod_pol_sel_2
+ type: range
+ blocks: "2"
+ policy_group: ansible_fabric_pod_pol_grp
+ register: nm_update_fabric_pod_sel_with_blocks
+
+- name: Create Fabric Pod Selector with blocks and policy again
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_blocks
+ blocks: "2"
+ register: nm_update_fabric_pod_sel_with_blocks_again
+
+- name: Update Fabric Pod Selector with blocks and policy again with different notation
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_blocks
+ blocks: "2-2"
+ register: nm_update_fabric_pod_sel_with_blocks_again_different_notation
+
+- name: Update Fabric Pod Selector with changed blocks range
+ cisco.aci.aci_fabric_pod_selector: &fabric_pod_sel_blocks_range
+ <<: *fabric_pod_sel_blocks
+ blocks: "2-3,5,8-11"
+ register: nm_update_fabric_pod_sel_with_blocks_range
+
+- name: Update Fabric Pod Selector with removal of policy group
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_blocks_range
+ policy_group: ""
+ register: nm_update_fabric_pod_sel_with_blocks_no_policy
+
+- name: Verify update of Pod Selector
+ ansible.builtin.assert:
+ that:
+ - nm_update_fabric_pod_sel_with_blocks is changed
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.children.1.fabricPodBlk.attributes.from_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks.current.0.fabricPodS.children.1.fabricPodBlk.attributes.to_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks.previous == []
+ - nm_update_fabric_pod_sel_with_blocks_again is not changed
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.children.1.fabricPodBlk.attributes.from_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_again.current.0.fabricPodS.children.1.fabricPodBlk.attributes.to_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.children.1.fabricPodBlk.attributes.from_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_again.previous.0.fabricPodS.children.1.fabricPodBlk.attributes.to_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation is not changed
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.children.1.fabricPodBlk.attributes.from_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.current.0.fabricPodS.children.1.fabricPodBlk.attributes.to_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.children.1.fabricPodBlk.attributes.from_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_again_different_notation.previous.0.fabricPodS.children.1.fabricPodBlk.attributes.to_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_range is changed
+ - nm_update_fabric_pod_sel_with_blocks_range.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_range.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_range.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_range.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_range.current.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_range.current.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks_range.current.0.fabricPodS.children | length == 4
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.children.1.fabricPodBlk.attributes.from_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_range.previous.0.fabricPodS.children.1.fabricPodBlk.attributes.to_ == "2"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy is changed
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.current.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.current.0.fabricPodS.children | length == 3
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.previous.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.previous.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.previous.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.previous.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.previous.0.fabricPodS.attributes.type == "range"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.previous.0.fabricPodS.children.0.fabricRsPodPGrp.attributes.tDn == "uni/fabric/funcprof/podpgrp-ansible_fabric_pod_pol_grp"
+ - nm_update_fabric_pod_sel_with_blocks_no_policy.previous.0.fabricPodS.children | length == 4
+
+# QUERY FABRIC POD SELECTOR
+- name: Create another Fabric Pod Selector
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_blocks
+ name: ansible_fabric_pod_pol_sel_3
+ blocks: "6"
+
+- name: Query a Fabric Pod Selector
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *fabric_pod_sel_blocks
+ state: query
+ register: query_one
+
+- name: Query all Fabric Pod Selectors
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify queries of Fabric Pod Selectors
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.fabricPodS.attributes.annotation == "orchestrator:ansible"
+ - query_one.current.0.fabricPodS.attributes.descr == "Created Ansible Pod Selector"
+ - query_one.current.0.fabricPodS.attributes.dn == "uni/fabric/podprof-default/pods-ansible_fabric_pod_pol_sel_2-typ-range"
+ - query_one.current.0.fabricPodS.attributes.name == "ansible_fabric_pod_pol_sel_2"
+ - query_one.current.0.fabricPodS.attributes.type == "range"
+ - query_one.current.0.fabricPodS.children | length == 3
+ - query_all is not changed
+ - query_all.current | length >= 2
+
+# ERRORS
+- name: Create Fabric Pod Selector with type range and without blocks (error)
+ cisco.aci.aci_fabric_pod_selector:
+ <<: *aci_info
+ name: ansible_fabric_pod_pol_sel_2
+ type: range
+ pod_profile: default
+ register: err_range_without_blocks
+ ignore_errors: true
+
+- name: Verify errors of Fabric Pod Selectors
+ ansible.builtin.assert:
+ that:
+ - err_range_without_blocks is not changed
+ - err_range_without_blocks is failed
+ - err_range_without_blocks.msg == "The 'blocks' parameter is required when the 'type' parameter is set to 'range' and 'state' parameter is set to 'present'."
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml
new file mode 100644
index 000000000..daf5e8956
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_scheduler/tasks/main.yml
@@ -0,0 +1,158 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Ensure first scheduler does not exist
+ aci_fabric_scheduler: &aci_fabric_scheduler_absent
+ <<: *aci_info
+ name: anstest_scheduler_reccuring
+ description: ACI scheduler test
+ windowname: Recurring
+ recurring: True
+ concurCap: 20
+ hour: 13
+ minute: 30
+ day: Tuesday
+ state: absent
+
+ - name: Ensure second scheduler does not exist
+ aci_fabric_scheduler: &aci_fabric_scheduler_2_absent
+ <<: *aci_info
+ name: anstest_scheduler_oneTime
+ windowname: OneTime
+ recurring: False
+ concurCap: 20
+ date: "2023-11-20T24:00:00"
+ state: absent
+
+ - name: Create first scheduler (check_mode)
+ aci_fabric_scheduler: &aci_fabric_scheduler_present
+ <<: *aci_fabric_scheduler_absent
+ state: present
+ check_mode: true
+ register: cm_add_fabric_scheduler_1
+
+ - name: Create first scheduler (normal_mode)
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ register: nm_add_fabric_scheduler_1
+
+ - name: Create first scheduler again - testing idempotency
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ register: idempotency_add_fabric_scheduler_1
+
+ - name: Create second scheduler
+ aci_fabric_scheduler: &aci_fabric_scheduler_2_present
+ <<: *aci_fabric_scheduler_2_absent
+ state: present
+ register: nm_add_fabric_scheduler_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_fabric_scheduler_1 is changed
+ - cm_add_fabric_scheduler_1.previous == []
+ - cm_add_fabric_scheduler_1.current == []
+ - nm_add_fabric_scheduler_1 is changed
+ - nm_add_fabric_scheduler_1.current.0.trigSchedP.attributes.name == "anstest_scheduler_reccuring"
+ - nm_add_fabric_scheduler_1.current.0.trigSchedP.attributes.descr == "ACI scheduler test"
+ - nm_add_fabric_scheduler_1.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.concurCap == "20"
+ - nm_add_fabric_scheduler_1.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.day == "Tuesday"
+ - nm_add_fabric_scheduler_1.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.hour == "13"
+ - nm_add_fabric_scheduler_1.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.minute == "30"
+ - idempotency_add_fabric_scheduler_1 is not changed
+ - nm_add_fabric_scheduler_2 is changed
+ - nm_add_fabric_scheduler_2.current.0.trigSchedP.attributes.name == "anstest_scheduler_oneTime"
+ - nm_add_fabric_scheduler_2.current.0.trigSchedP.children.0.trigAbsWindowP.attributes.concurCap == "20"
+ - nm_add_fabric_scheduler_2.current.0.trigSchedP.children.0.trigAbsWindowP.attributes.date == "2023-11-21T00:00:00.000+00:00"
+
+ - name: Query all scheduler
+ aci_fabric_scheduler:
+ <<: *aci_info
+ state: query
+ register: query_all_fabric_scheduler
+
+ - name: Query first scheduler
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ state: query
+ register: query_first_fabric_scheduler
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_fabric_scheduler is not changed
+ - query_all_fabric_scheduler.current | length >= 2
+ - '"trigAbsWindowP,trigRecurrWindowP" in query_all_fabric_scheduler.filter_string'
+ - '"class/trigSchedP.json" in query_all_fabric_scheduler.url'
+ - query_first_fabric_scheduler is not changed
+ - query_first_fabric_scheduler.current.0.trigSchedP.attributes.name == "anstest_scheduler_reccuring"
+ - query_first_fabric_scheduler.current.0.trigSchedP.attributes.descr == "ACI scheduler test"
+ - query_first_fabric_scheduler.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.concurCap == "20"
+ - query_first_fabric_scheduler.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.day == "Tuesday"
+ - query_first_fabric_scheduler.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.hour == "13"
+ - query_first_fabric_scheduler.current.0.trigSchedP.children.0.trigRecurrWindowP.attributes.minute == "30"
+
+ - name: Delete first scheduler (check_mode)
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ state: absent
+ check_mode: true
+ register: cm_delete_fabric_scheduler_1
+
+ - name: Delete first scheduler (normal_mode)
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ state: absent
+ register: nm_delete_fabric_scheduler_1
+
+ - name: Delete first scheduler again - testing idempotency
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ state: absent
+ register: idempotency_delete_maintenance_group_1
+
+ - name: Delete second scheduler (normal_mode)
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_2_present
+ state: absent
+ register: nm_delete_fabric_scheduler_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_fabric_scheduler_1 is changed
+ - cm_delete_fabric_scheduler_1.proposed == {}
+ - nm_delete_fabric_scheduler_1 is changed
+ - nm_delete_fabric_scheduler_1.previous != []
+ - nm_delete_fabric_scheduler_1.current == []
+ - idempotency_delete_maintenance_group_1 is not changed
+ - idempotency_delete_maintenance_group_1.previous == []
+ - nm_delete_fabric_scheduler_2 is changed
+ - nm_delete_fabric_scheduler_2.previous != []
+ - nm_delete_fabric_scheduler_2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml
new file mode 100644
index 000000000..a67026daa
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_dst_group/tasks/main.yml
@@ -0,0 +1,264 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (akinross@cisco.com)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ ansible.builtin.set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+# TEST CREATE AND UPDATE DESTINATION GROUPS
+
+- name: Add fabric span destination group 1 ( check mode )
+ cisco.aci.aci_fabric_span_dst_group: &add_ansible_group_1
+ <<: *aci_info
+ destination_group: ansible_group_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+ check_mode: true
+ register: cm_add_ansible_group_1
+
+- name: Add fabric span destination group 1
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *add_ansible_group_1
+ register: nm_add_ansible_group_1
+
+- name: Add fabric span destination group 1 again
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *add_ansible_group_1
+ register: nm_add_ansible_group_1_again
+
+- name: Verify add fabric span destination group 1
+ ansible.builtin.assert:
+ that:
+ - cm_add_ansible_group_1 is changed
+ - cm_add_ansible_group_1.current == []
+ - cm_add_ansible_group_1.previous == []
+ - cm_add_ansible_group_1.proposed.spanDestGrp.attributes.name == "ansible_group_1"
+ - cm_add_ansible_group_1.proposed.spanDestGrp.attributes.descr == "test span epg"
+ - cm_add_ansible_group_1.proposed.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_1"
+ - cm_add_ansible_group_1.proposed.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
+ - cm_add_ansible_group_1.proposed.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
+ - cm_add_ansible_group_1.proposed.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.tDn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test"
+ - nm_add_ansible_group_1 is changed
+ - nm_add_ansible_group_1.previous == []
+ - nm_add_ansible_group_1.current.0.spanDestGrp.attributes.name == "ansible_group_1"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.attributes.descr == "test span epg"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_1"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "unspecified"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1518"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.tDn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "64"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver2"
+ - nm_add_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "no"
+ - nm_add_ansible_group_1_again is not changed
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.attributes.name == "ansible_group_1"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.attributes.descr == "test span epg"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_1"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "unspecified"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1518"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.tDn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "64"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver2"
+ - nm_add_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "no"
+
+- name: Change fabric span destination group 1
+ cisco.aci.aci_fabric_span_dst_group: &change_ansible_group_1
+ <<: *aci_info
+ destination_group: ansible_group_1
+ description: changed test span epg
+ destination_epg:
+ destination_ip: 10.0.0.2
+ source_ip: 10.0.2.2
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ version_enforced: true
+ span_version: version_1
+ ttl: 4
+ mtu: 1500
+ flow_id: 2
+ dscp: "VA"
+ register: change_ansible_group_1
+
+- name: Apply same changes to fabric span destination group 1
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *change_ansible_group_1
+ register: change_ansible_group_1_again
+
+- name: Verify change fabric span destination group 1
+ ansible.builtin.assert:
+ that:
+ - change_ansible_group_1 is changed
+ - change_ansible_group_1.previous.0.spanDestGrp.attributes.name == "ansible_group_1"
+ - change_ansible_group_1.previous.0.spanDestGrp.attributes.descr == "test span epg"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_1"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "unspecified"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1518"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.tDn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "64"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver2"
+ - change_ansible_group_1.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "no"
+ - change_ansible_group_1.current.0.spanDestGrp.attributes.name == "ansible_group_1"
+ - change_ansible_group_1.current.0.spanDestGrp.attributes.descr == "changed test span epg"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_1"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "VA"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "2"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.2"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.2"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.tDn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "4"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver1"
+ - change_ansible_group_1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "yes"
+ - change_ansible_group_1_again is not changed
+ - change_ansible_group_1_again.previous.0.spanDestGrp.attributes.name == "ansible_group_1"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.attributes.descr == "changed test span epg"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_1"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "VA"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "2"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.2"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.2"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.tDn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "4"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver1"
+ - change_ansible_group_1_again.previous.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "yes"
+ - change_ansible_group_1_again.current.0.spanDestGrp.attributes.name == "ansible_group_1"
+ - change_ansible_group_1_again.current.0.spanDestGrp.attributes.descr == "changed test span epg"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_1"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "VA"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "2"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.2"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.2"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.tDn == "uni/tn-ansible_test/ap-ansible_test/epg-ansible_test"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "4"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver1"
+ - change_ansible_group_1_again.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "yes"
+
+- name: Add another fabric span destination group 2 for query all
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_group_2
+ description: test span epg 2
+ destination_epg:
+ destination_ip: 10.0.0.3
+ source_ip: 10.0.2.3
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+# TEST QUERY DESTINATION GROUPS
+
+- name: Query one fabric span destination group 1
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *add_ansible_group_1
+ state: query
+ register: query_one
+
+- name: Query all fabric span destination groups
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying fabric span destination groups
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanDestGrp.attributes.name == "ansible_group_1"
+ - query_all is not changed
+ - query_all.current | length >= 2 # greater or equal because there could be configuration present that is not fabric span but is returned in ( class based ) query all
+
+# TEST REMOVAL DESTINATION GROUPS
+
+- name: Remove fabric span destination group 1 ( check mode )
+ cisco.aci.aci_fabric_span_dst_group: &remove_ansible_group_1
+ <<: *add_ansible_group_1
+ state: absent
+ check_mode: true
+ register: cm_remove_ansible_group_1
+
+- name: Remove fabric span destination group 1
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *remove_ansible_group_1
+ register: nm_remove_ansible_group_1
+
+- name: Remove fabric span destination group 1 again
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *remove_ansible_group_1
+ register: nm_remove_ansible_group_1_again
+
+- name: Verify remove fabric span destination group 1
+ ansible.builtin.assert:
+ that:
+ - cm_remove_ansible_group_1 is changed
+ - cm_remove_ansible_group_1.current | length == 1
+ - cm_remove_ansible_group_1.previous | length == 1
+ - cm_remove_ansible_group_1.proposed == {}
+ - nm_remove_ansible_group_1 is changed
+ - nm_remove_ansible_group_1.current == []
+ - nm_remove_ansible_group_1.previous | length == 1
+ - nm_remove_ansible_group_1_again is not changed
+ - nm_remove_ansible_group_1_again.current == []
+ - nm_remove_ansible_group_1_again.previous == []
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml
new file mode 100644
index 000000000..c3e4eb55c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group/tasks/main.yml
@@ -0,0 +1,245 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Add fabric span destination group 1 ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+# TEST CREATE AND UPDATE SOURCE GROUPS
+
+- name: Add fabric span source group 1 ( checkmode )
+ cisco.aci.aci_fabric_span_src_group: &span_src_1
+ <<: *aci_info
+ source_group: span_src_1
+ destination_group: span_dest_1
+ state: present
+ check_mode: true
+ register: cm_span_src_1
+
+- name: Add fabric span source group 1
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *span_src_1
+ register: nm_span_src_1
+
+- name: Add fabric span source group 1 again
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *span_src_1
+ register: nm_span_src_1_again
+
+- name: Verify add fabric span source group 1
+ ansible.builtin.assert:
+ that:
+ - cm_span_src_1 is changed
+ - cm_span_src_1.previous == []
+ - cm_span_src_1.current == []
+ - cm_span_src_1.proposed.spanSrcGrp.attributes.name == "span_src_1"
+ - cm_span_src_1.proposed.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_span_src_1 is changed
+ - nm_span_src_1.previous == []
+ - nm_span_src_1.current.0.spanSrcGrp.attributes.name == "span_src_1"
+ - nm_span_src_1.current.0.spanSrcGrp.attributes.descr == ""
+ - nm_span_src_1.current.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_span_src_1.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_span_src_1_again is not changed
+ - nm_span_src_1_again.previous.0.spanSrcGrp.attributes.name == "span_src_1"
+ - nm_span_src_1_again.previous.0.spanSrcGrp.attributes.descr == ""
+ - nm_span_src_1_again.previous.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_span_src_1_again.previous.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_span_src_1_again.current.0.spanSrcGrp.attributes.name == "span_src_1"
+ - nm_span_src_1_again.current.0.spanSrcGrp.attributes.descr == ""
+ - nm_span_src_1_again.current.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_span_src_1_again.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_1"
+
+- name: Change fabric span source group 1
+ cisco.aci.aci_fabric_span_src_group: &change_span_src_1
+ <<: *span_src_1
+ destination_group: span_dest_2
+ description: "changed description"
+ admin_state: false
+ register: nm_changed_span_src_1
+
+- name: Change fabric span source group 1 again
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *change_span_src_1
+ register: nm_changed_span_src_1_again
+
+- name: Verify changed fabric span source group 1
+ ansible.builtin.assert:
+ that:
+ - nm_changed_span_src_1 is changed
+ - nm_changed_span_src_1.previous.0.spanSrcGrp.attributes.descr == ""
+ - nm_changed_span_src_1.previous.0.spanSrcGrp.attributes.adminSt == "enabled"
+ - nm_changed_span_src_1.previous.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_1"
+ - nm_changed_span_src_1.current.0.spanSrcGrp.attributes.descr == "changed description"
+ - nm_changed_span_src_1.current.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_1.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_2"
+ - nm_changed_span_src_1_again is not changed
+ - nm_changed_span_src_1_again.previous.0.spanSrcGrp.attributes.descr == "changed description"
+ - nm_changed_span_src_1_again.previous.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_1_again.previous.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_2"
+ - nm_changed_span_src_1_again.current.0.spanSrcGrp.attributes.descr == "changed description"
+ - nm_changed_span_src_1_again.current.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_1_again.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "span_dest_2"
+
+- name: Add fabric span source group 2 with admin_state to false
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *change_span_src_1
+ source_group: span_src_2
+ destination_group: span_dest_2
+ admin_state: false
+ register: nm_changed_span_src_2_admin_state_false
+
+- name: Add fabric span source group 3 with admin_state to true
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *change_span_src_1
+ source_group: span_src_3
+ destination_group: span_dest_3
+ admin_state: true
+ register: nm_changed_span_src_3_admin_state_true
+
+- name: Verify admin_state sets for fabric span source group 2 and 3
+ ansible.builtin.assert:
+ that:
+ - nm_changed_span_src_2_admin_state_false is changed
+ - nm_changed_span_src_2_admin_state_false.current.0.spanSrcGrp.attributes.adminSt == "disabled"
+ - nm_changed_span_src_3_admin_state_true is changed
+ - nm_changed_span_src_3_admin_state_true.current.0.spanSrcGrp.attributes.adminSt == "enabled"
+
+# TEST QUERY SOURCE GROUPS
+
+- name: Query fabric span source group span_src_1
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *change_span_src_1
+ state: query
+ register: query_one
+
+- name: Query all span source groups
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying fabric span destination groups
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanSrcGrp.attributes.name == "span_src_1"
+ - query_all is not changed
+ - query_all.current | length >= 3
+
+# TEST REMOVAL SOURCE GROUPS
+
+- name: Remove fabric span source group ( checkmode )
+ cisco.aci.aci_fabric_span_src_group: &remove_span_src_1
+ <<: *change_span_src_1
+ state: absent
+ check_mode: true
+ register: cm_remove_span_src_1
+
+- name: Remove fabric span source group 1
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *remove_span_src_1
+ register: nm_remove_span_src_1
+
+- name: Remove fabric span source group 1 again
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *remove_span_src_1
+ register: nm_remove_span_src_1_again
+
+- name: Verify remove fabric span source group 1
+ ansible.builtin.assert:
+ that:
+ - cm_remove_span_src_1 is changed
+ - cm_remove_span_src_1.current | length == 1
+ - cm_remove_span_src_1.previous | length == 1
+ - cm_remove_span_src_1.proposed == {}
+ - nm_remove_span_src_1 is changed
+ - nm_remove_span_src_1.current == []
+ - nm_remove_span_src_1.previous | length == 1
+ - nm_remove_span_src_1_again is not changed
+ - nm_remove_span_src_1_again.current == []
+ - nm_remove_span_src_1_again.previous == []
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml
new file mode 100644
index 000000000..6767e3e89
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src/tasks/main.yml
@@ -0,0 +1,396 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Add fabric span destination group type epg ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+- name: Add fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item }}"
+ destination_group: span_dest_1
+ state: present
+ loop:
+ - span_src_group_1
+ - span_src_group_2
+
+# TEST CREATE AND UPDATE SOURCE
+
+- name: Add fabric span source 1 ( checkmode )
+ cisco.aci.aci_fabric_span_src_group_src: &fabric_span_src_1
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: fabric_span_src_1
+ state: present
+ check_mode: true
+ register: cm_fabric_span_src_1
+
+- name: Add fabric span source 1
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *fabric_span_src_1
+ register: nm_fabric_span_src_1
+
+- name: Add fabric span source 1 again
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *fabric_span_src_1
+ register: nm_fabric_span_src_1_again
+
+- name: Verify add fabric span source 1
+ ansible.builtin.assert:
+ that:
+ - cm_fabric_span_src_1 is changed
+ - cm_fabric_span_src_1.previous == []
+ - cm_fabric_span_src_1.current == []
+ - cm_fabric_span_src_1.proposed.spanSrc.attributes.name == "fabric_span_src_1"
+ - cm_fabric_span_src_1.proposed.spanSrc.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-fabric_span_src_1"
+ - nm_fabric_span_src_1 is changed
+ - nm_fabric_span_src_1.previous == []
+ - nm_fabric_span_src_1.current.0.spanSrc.attributes.name == "fabric_span_src_1"
+ - nm_fabric_span_src_1.current.0.spanSrc.attributes.descr == ""
+ - nm_fabric_span_src_1.current.0.spanSrc.attributes.dir == "both"
+ - nm_fabric_span_src_1.current.0.spanSrc.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-fabric_span_src_1"
+ - nm_fabric_span_src_1_again is not changed
+ - nm_fabric_span_src_1_again.previous.0.spanSrc.attributes.name == "fabric_span_src_1"
+ - nm_fabric_span_src_1_again.previous.0.spanSrc.attributes.descr == ""
+ - nm_fabric_span_src_1_again.previous.0.spanSrc.attributes.dir == "both"
+ - nm_fabric_span_src_1_again.previous.0.spanSrc.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-fabric_span_src_1"
+ - nm_fabric_span_src_1_again.current.0.spanSrc.attributes.name == "fabric_span_src_1"
+ - nm_fabric_span_src_1_again.current.0.spanSrc.attributes.descr == ""
+ - nm_fabric_span_src_1_again.current.0.spanSrc.attributes.dir == "both"
+ - nm_fabric_span_src_1_again.current.0.spanSrc.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-fabric_span_src_1"
+
+- name: Change fabric span source 1
+ cisco.aci.aci_fabric_span_src_group_src: &change_fabric_span_src_1
+ <<: *fabric_span_src_1
+ source: fabric_span_src_1
+ description: "changed description"
+ direction: both
+ register: nm_changed_fabric_span_src_1
+
+- name: Change fabric span source 1 direction incoming
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *change_fabric_span_src_1
+ direction: incoming
+ register: nm_changed_fabric_span_src_1_incoming
+
+- name: Change fabric span source 1 direction outgoing
+ cisco.aci.aci_fabric_span_src_group_src: &change_fabric_span_src_1_again
+ <<: *change_fabric_span_src_1
+ direction: outgoing
+ register: nm_changed_fabric_span_src_1_outgoing
+
+- name: Change fabric span source 1 again
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *change_fabric_span_src_1_again
+ register: nm_changed_fabric_span_src_1_again
+
+- name: Verify changed fabric span source 1
+ ansible.builtin.assert:
+ that:
+ - nm_changed_fabric_span_src_1 is changed
+ - nm_changed_fabric_span_src_1.previous.0.spanSrc.attributes.name == "fabric_span_src_1"
+ - nm_changed_fabric_span_src_1.previous.0.spanSrc.attributes.descr == ""
+ - nm_changed_fabric_span_src_1.previous.0.spanSrc.attributes.dir == "both"
+ - nm_changed_fabric_span_src_1.previous.0.spanSrc.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-fabric_span_src_1"
+ - nm_changed_fabric_span_src_1.current.0.spanSrc.attributes.name == "fabric_span_src_1"
+ - nm_changed_fabric_span_src_1.current.0.spanSrc.attributes.descr == "changed description"
+ - nm_changed_fabric_span_src_1.current.0.spanSrc.attributes.dir == "both"
+ - nm_changed_fabric_span_src_1.current.0.spanSrc.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-fabric_span_src_1"
+ - nm_changed_fabric_span_src_1_incoming.current.0.spanSrc.attributes.dir == "in"
+ - nm_changed_fabric_span_src_1_outgoing.current.0.spanSrc.attributes.dir == "out"
+ - nm_changed_fabric_span_src_1_again is not changed
+
+- name: Add fabric span source 2 of bd type
+ cisco.aci.aci_fabric_span_src_group_src: &span_src_bd
+ <<: *aci_info
+ source_group: span_src_group_1
+ bd:
+ tenant: tenant1
+ bd: bd1
+ source: fabric_span_src_2
+ state: present
+ register: nm_fabric_span_src_2
+
+- name: Change fabric span source 2 of bd type
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *span_src_bd
+ bd:
+ tenant: tenant1
+ bd: bd2
+ register: nm_changed_fabric_span_src_2
+
+- name: Change fabric span source 2 of bd type to none type
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: fabric_span_src_2
+ state: present
+ register: nm_changed_fabric_span_src_2_type_none
+
+- name: Add fabric span source 3 of vrf type
+ cisco.aci.aci_fabric_span_src_group_src: &span_src_vrf
+ <<: *aci_info
+ source_group: span_src_group_1
+ vrf:
+ tenant: tenant1
+ vrf: vrf1
+ source: fabric_span_src_3
+ state: present
+ register: nm_fabric_span_src_3
+
+- name: Change fabric span source 3 of vrf type
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *span_src_vrf
+ vrf:
+ tenant: tenant1
+ vrf: vrf2
+ register: nm_changed_fabric_span_src_3
+
+- name: Change fabric span source 3 of vrf type
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: fabric_span_src_3
+ state: present
+ register: nm_changed_fabric_span_src_3_type_none
+
+- name: Verify changed fabric span source types group 2 and 3
+ ansible.builtin.assert:
+ that:
+ - nm_fabric_span_src_2 is changed
+ - nm_fabric_span_src_2.current.0.spanSrc.attributes.name == "fabric_span_src_2"
+ - nm_fabric_span_src_2.current.0.spanSrc.children.0.spanRsSrcToBD.attributes.tDn == "uni/tn-tenant1/BD-bd1"
+ - nm_changed_fabric_span_src_2 is changed
+ - nm_changed_fabric_span_src_2.current.0.spanSrc.attributes.name == "fabric_span_src_2"
+ - nm_changed_fabric_span_src_2.previous.0.spanSrc.children.0.spanRsSrcToBD.attributes.tDn == "uni/tn-tenant1/BD-bd1"
+ - nm_changed_fabric_span_src_2.current.0.spanSrc.children.0.spanRsSrcToBD.attributes.tDn == "uni/tn-tenant1/BD-bd2"
+ - nm_changed_fabric_span_src_2_type_none is changed
+ - nm_changed_fabric_span_src_2_type_none.previous.0.spanSrc.children.0.spanRsSrcToBD.attributes.tDn == "uni/tn-tenant1/BD-bd2"
+ - '"children" not in nm_changed_fabric_span_src_2_type_none.current.0.spanSrc'
+ - nm_fabric_span_src_3 is changed
+ - nm_fabric_span_src_3.current.0.spanSrc.attributes.name == "fabric_span_src_3"
+ - nm_fabric_span_src_3.current.0.spanSrc.children.0.spanRsSrcToCtx.attributes.tDn == "uni/tn-tenant1/ctx-vrf1"
+ - nm_changed_fabric_span_src_3 is changed
+ - nm_changed_fabric_span_src_3.current.0.spanSrc.attributes.name == "fabric_span_src_3"
+ - nm_changed_fabric_span_src_3.previous.0.spanSrc.children.0.spanRsSrcToCtx.attributes.tDn == "uni/tn-tenant1/ctx-vrf1"
+ - nm_changed_fabric_span_src_3.current.0.spanSrc.children.0.spanRsSrcToCtx.attributes.tDn == "uni/tn-tenant1/ctx-vrf2"
+ - nm_changed_fabric_span_src_3_type_none is changed
+ - nm_changed_fabric_span_src_3_type_none.previous.0.spanSrc.children.0.spanRsSrcToCtx.attributes.tDn == "uni/tn-tenant1/ctx-vrf2"
+ - '"children" not in nm_changed_fabric_span_src_3_type_none.current.0.spanSrc'
+
+- name: Change fabric span source 4 drop_packets true
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_2
+ source: span_src_4
+ drop_packets: true
+ state: present
+ register: nm_changed_span_src_4_type_drop_packets_true
+
+- name: Change fabric span source 4 drop_packets false
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_2
+ source: span_src_4
+ drop_packets: false
+ state: present
+ register: nm_changed_span_src_4_type_drop_packets_false
+
+- name: Verify changed fabric span source group 1 drop packets
+ ansible.builtin.assert:
+ that:
+ - nm_changed_span_src_4_type_drop_packets_true is changed
+ - nm_changed_span_src_4_type_drop_packets_true.current.0.spanSrc.attributes.name == "span_src_4"
+ - nm_changed_span_src_4_type_drop_packets_true.current.0.spanSrc.attributes.spanOnDrop == "yes"
+ - nm_changed_span_src_4_type_drop_packets_false is changed
+ - nm_changed_span_src_4_type_drop_packets_false.current.0.spanSrc.attributes.name == "span_src_4"
+ - nm_changed_span_src_4_type_drop_packets_false.current.0.spanSrc.attributes.spanOnDrop == "no"
+
+# TEST QUERY SOURCE
+
+- name: Query fabric span source fabric_span_src_1
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source: fabric_span_src_1
+ state: query
+ register: query_one
+
+- name: Query fabric all span sources
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying fabric span sources
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanSrc.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-fabric_span_src_1"
+ - query_all is not changed
+ - query_all.current | length >= 3
+
+# TEST ERRORS SOURCE
+
+- name: Add fabric span source 4 with bd and vrf ( mutually exclusive error )
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ bd:
+ tenant: tenant1
+ bd: bd1
+ vrf:
+ tenant: tenant1
+ vrf: vrf1
+ source: span_src_4
+ state: present
+ ignore_errors: true
+ register: err_mutually_exclusive_bd_vrf
+
+- name: Add fabric span source 4 with bd and drop_packets( drop_packets true error )
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ source: span_src_4
+ bd:
+ tenant: tenant1
+ bd: bd1
+ drop_packets: true
+ ignore_errors: true
+ register: err_bd_drop_packets
+
+- name: Add fabric span source 4 with vrf and drop_packets ( drop_packets true error )
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_4
+ source: span_src_4
+ vrf:
+ tenant: tenant1
+ vrf: vrf1
+ drop_packets: true
+ ignore_errors: true
+ register: err_vrf_drop_packets
+
+- name: Verify errors on incorrect input
+ ansible.builtin.assert:
+ that:
+ - err_mutually_exclusive_bd_vrf.msg == "parameters are mutually exclusive{{':'}} vrf|bd"
+ - err_bd_drop_packets.msg == "It is not allowed to configure 'drop_packets{{':'}} true' when 'bd' is configured on the source."
+ - err_vrf_drop_packets.msg == "It is not allowed to configure 'drop_packets{{':'}} true' when 'vrf' is configured on the source."
+
+# TEST REMOVAL SOURCE
+
+- name: Remove fabric span source 1 ( checkmode )
+ cisco.aci.aci_fabric_span_src_group_src: &remove_fabric_span_src_1
+ <<: *change_fabric_span_src_1
+ state: absent
+ check_mode: true
+ register: cm_remove_fabric_span_src_1
+
+- name: Remove fabric span source 1
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *remove_fabric_span_src_1
+ register: nm_remove_fabric_span_src_1
+
+- name: Remove fabric span source 1 again
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *remove_fabric_span_src_1
+ register: nm_remove_fabric_span_src_1_again
+
+- name: Verify remove fabric span source 1
+ ansible.builtin.assert:
+ that:
+ - cm_remove_fabric_span_src_1 is changed
+ - cm_remove_fabric_span_src_1.current | length == 1
+ - cm_remove_fabric_span_src_1.previous | length == 1
+ - cm_remove_fabric_span_src_1.proposed == {}
+ - nm_remove_fabric_span_src_1 is changed
+ - nm_remove_fabric_span_src_1.current == []
+ - nm_remove_fabric_span_src_1.previous | length == 1
+ - nm_remove_fabric_span_src_1_again is not changed
+ - nm_remove_fabric_span_src_1_again.current == []
+ - nm_remove_fabric_span_src_1_again.previous == []
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml
new file mode 100644
index 000000000..0e5ea30b2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_node/tasks/main.yml
@@ -0,0 +1,238 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Add fabric span destination group type epg ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+- name: Add fabric span source group 1 ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: span_src_group_1
+ destination_group: span_dest_1
+ state: present
+
+- name: Add fabric span source group source 1 ( clean before )
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ drop_packets: true
+ state: present
+
+- name: Add fabric span source group source 2 for error handling ( clean before )
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_2
+ drop_packets: false
+ state: present
+
+
+# TEST CREATE SOURCE NODES
+
+- name: Add fabric span source node 1 ( checkmode )
+ cisco.aci.aci_fabric_span_src_group_src_node: &span_src_node_1
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ node: 101
+ state: present
+ check_mode: true
+ register: cm_span_src_node_1
+
+- name: Add fabric span source node 1
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *span_src_node_1
+ register: nm_span_src_node_1
+
+- name: Add fabric span source node 1 again
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *span_src_node_1
+ register: nm_span_src_node_1_again
+
+- name: Verify add fabric span source node 1
+ ansible.builtin.assert:
+ that:
+ - cm_span_src_node_1 is changed
+ - cm_span_src_node_1.previous == []
+ - cm_span_src_node_1.current == []
+ - cm_span_src_node_1.proposed.spanRsSrcToNode.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToNode-[topology/pod-1/node-101]"
+ - cm_span_src_node_1.proposed.spanRsSrcToNode.attributes.tDn == "topology/pod-1/node-101"
+ - nm_span_src_node_1 is changed
+ - nm_span_src_node_1.current.0.spanRsSrcToNode.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToNode-[topology/pod-1/node-101]"
+ - nm_span_src_node_1.current.0.spanRsSrcToNode.attributes.tDn == "topology/pod-1/node-101"
+ - nm_span_src_node_1.previous == []
+ - nm_span_src_node_1_again is not changed
+ - nm_span_src_node_1_again.previous.0.spanRsSrcToNode.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToNode-[topology/pod-1/node-101]"
+ - nm_span_src_node_1_again.previous.0.spanRsSrcToNode.attributes.tDn == "topology/pod-1/node-101"
+ - nm_span_src_node_1_again.current.0.spanRsSrcToNode.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToNode-[topology/pod-1/node-101]"
+ - nm_span_src_node_1_again.current.0.spanRsSrcToNode.attributes.tDn == "topology/pod-1/node-101"
+
+- name: Add fabric span source node 2
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ node: 102
+ state: present
+
+# TEST QUERY SOURCE NODES
+
+- name: Query fabric span source node 1
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *span_src_node_1
+ state: query
+ register: query_one
+
+- name: Query all fabric span source nodes
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying fabric span sources
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanRsSrcToNode.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToNode-[topology/pod-1/node-101]"
+ - query_one.current.0.spanRsSrcToNode.attributes.tDn == "topology/pod-1/node-101"
+ - query_all is not changed
+ - query_all.current | length >= 2
+
+# TEST REMOVAL SOURCE NODES
+
+- name: Remove fabric span source node 1 ( checkmode )
+ cisco.aci.aci_fabric_span_src_group_src_node: &remove_span_src_node_1
+ <<: *span_src_node_1
+ state: absent
+ check_mode: true
+ register: cm_remove_span_src_node_1
+
+- name: Remove fabric span source node 1
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *remove_span_src_node_1
+ register: nm_remove_span_src_node_1
+
+- name: Remove fabric span source node 1 again
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *remove_span_src_node_1
+ register: nm_remove_span_src_node_1_again
+
+- name: Verify remove fabric span source node 1
+ ansible.builtin.assert:
+ that:
+ - cm_remove_span_src_node_1 is changed
+ - cm_remove_span_src_node_1.current | length == 1
+ - cm_remove_span_src_node_1.previous | length == 1
+ - cm_remove_span_src_node_1.proposed == {}
+ - nm_remove_span_src_node_1 is changed
+ - nm_remove_span_src_node_1.current == []
+ - nm_remove_span_src_node_1.previous | length == 1
+ - nm_remove_span_src_node_1_again is not changed
+ - nm_remove_span_src_node_1_again.current == []
+ - nm_remove_span_src_node_1_again.previous == []
+
+# TEST ERROR SOURCE NODES
+
+- name: Add fabric span source node 2 (error)
+ cisco.aci.aci_fabric_span_src_group_src_node:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_2
+ pod: 1
+ node: 101
+ state: present
+ ignore_errors: true
+ register: err_drop_packets_on_src
+
+- name: Verify errors span source node 2
+ ansible.builtin.assert:
+ that:
+ - err_drop_packets_on_src.msg == "APIC Error 105{{':'}} Node span is supported only with Span on drop configuration"
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml
new file mode 100644
index 000000000..e0c772843
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_span_src_group_src_path/tasks/main.yml
@@ -0,0 +1,218 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("debug") }}'
+
+# CLEAN TEST ENVIRONMENT BEFORE TESTS
+
+- name: Query all fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Add fabric span destination group type epg ( clean before )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: span_dest_1
+ description: test span epg
+ destination_epg:
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_test
+ ap: ansible_test
+ epg: ansible_test
+ state: present
+
+- name: Add fabric span source group 1 ( clean before )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: span_src_group_1
+ destination_group: span_dest_1
+ state: present
+
+- name: Add fabric span source group source 1 ( clean before )
+ cisco.aci.aci_fabric_span_src_group_src:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ state: present
+
+# TEST CREATE SOURCE PATHS
+
+- name: Add fabric span source path 1 ( checkmode )
+ cisco.aci.aci_fabric_span_src_group_src_path: &span_src_path_1
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ node: 101
+ path_ep: eth1/1
+ state: present
+ check_mode: true
+ register: cm_span_src_path_1
+
+- name: Add fabric span source path 1
+ cisco.aci.aci_fabric_span_src_group_src_path:
+ <<: *span_src_path_1
+ register: nm_span_src_path_1
+
+- name: Add fabric span source path 1 again
+ cisco.aci.aci_fabric_span_src_group_src_path:
+ <<: *span_src_path_1
+ register: nm_span_src_path_1_again
+
+- name: Verify add fabric span source path 1
+ ansible.builtin.assert:
+ that:
+ - cm_span_src_path_1 is changed
+ - cm_span_src_path_1.previous == []
+ - cm_span_src_path_1.current == []
+ - cm_span_src_path_1.proposed.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - cm_span_src_path_1.proposed.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_span_src_path_1 is changed
+ - nm_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_span_src_path_1.previous == []
+ - nm_span_src_path_1_again is not changed
+ - nm_span_src_path_1_again.previous.0.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_span_src_path_1_again.previous.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_span_src_path_1_again.current.0.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_span_src_path_1_again.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+
+- name: Add fabric span source path 2
+ cisco.aci.aci_fabric_span_src_group_src_path:
+ <<: *aci_info
+ source_group: span_src_group_1
+ source: span_src_1
+ pod: 1
+ node: 102
+ path_ep: eth1/2
+ state: present
+
+# TEST QUERY SOURCE PATHS
+
+- name: Query fabric span source path 1
+ cisco.aci.aci_fabric_span_src_group_src_path:
+ <<: *span_src_path_1
+ state: query
+ register: query_one
+
+- name: Query all fabric span source paths
+ cisco.aci.aci_fabric_span_src_group_src_path:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify querying fabric span sources
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - query_one.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - query_all is not changed
+ - query_all.current | length >= 2
+
+# TEST REMOVAL SOURCE PATHS
+
+- name: Remove fabric span source path 1 ( checkmode )
+ cisco.aci.aci_fabric_span_src_group_src_path: &remove_span_src_path_1
+ <<: *span_src_path_1
+ state: absent
+ check_mode: true
+ register: cm_remove_span_src_path_1
+
+- name: Remove fabric span source path 1
+ cisco.aci.aci_fabric_span_src_group_src_path:
+ <<: *remove_span_src_path_1
+ register: nm_remove_span_src_path_1
+
+- name: Remove fabric span source path 1 again
+ cisco.aci.aci_fabric_span_src_group_src_path:
+ <<: *remove_span_src_path_1
+ register: nm_remove_span_src_path_1_again
+
+- name: Verify remove fabric span source path 1
+ ansible.builtin.assert:
+ that:
+ - cm_remove_span_src_path_1 is changed
+ - cm_remove_span_src_path_1.current | length == 1
+ - cm_remove_span_src_path_1.previous | length == 1
+ - cm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - cm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - cm_remove_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - cm_remove_span_src_path_1.current.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - cm_remove_span_src_path_1.proposed == {}
+ - nm_remove_span_src_path_1 is changed
+ - nm_remove_span_src_path_1.current == []
+ - nm_remove_span_src_path_1.previous | length == 1
+ - nm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.dn == "uni/fabric/srcgrp-span_src_group_1/src-span_src_1/rssrcToPathEp-[topology/pod-1/paths-101/pathep-[eth1/1]]"
+ - nm_remove_span_src_path_1.previous.0.spanRsSrcToPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - nm_remove_span_src_path_1_again is not changed
+ - nm_remove_span_src_path_1_again.current == []
+ - nm_remove_span_src_path_1_again.previous == []
+
+# CLEAN TEST ENVIRONMENT AFTER TESTS
+
+- name: Query all fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span source groups ( clean after )
+ cisco.aci.aci_fabric_span_src_group:
+ <<: *aci_info
+ source_group: "{{ item.spanSrcGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+- name: Query all fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean fabric span destination groups ( clean after )
+ cisco.aci.aci_fabric_span_dst_group:
+ <<: *aci_info
+ destination_group: "{{ item.spanDestGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml
new file mode 100644
index 000000000..526c8bee0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_wide_settings/tasks/main.yml
@@ -0,0 +1,229 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Tim Cragg (@timcragg)
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+- 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 skip execution for cloud sites
+ block:
+
+ # STORE EXISTING FABRIC WIDE SETTINGS
+ - name: Query system information
+ cisco.aci.aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+ - name: Capture existing Fabric Wide Settings
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_info
+ state: query
+ register: previous_settings
+
+ - name: Clear existing settings
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_info
+ disable_remote_ep_learning: false
+ enforce_subnet_check: false
+ enforce_epg_vlan_validation: false
+ spine_opflex_client_auth: false
+ spine_ssl_opflex: false
+
+ # SET FABRIC WIDE SETTINGS
+ - name: Execute tests for ACI v5+
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+ block:
+
+ - name: Clear existing settings for ACI v5+
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_info
+ leaf_opflex_client_auth: false
+ leaf_ssl_opflex: false
+ restrict_infra_vlan_traffic: false
+ opflex_ssl_versions: [ tls_v1.2 ]
+
+ - name: Update Fabric Wide Settings for ACI v5+ (check_mode)
+ cisco.aci.aci_fabric_wide_settings: &aci_fab_settings_5
+ <<: *aci_info
+ disable_remote_ep_learning: true
+ enforce_subnet_check: true
+ enforce_epg_vlan_validation: true
+ spine_opflex_client_auth: true
+ leaf_opflex_client_auth: true
+ spine_ssl_opflex: true
+ leaf_ssl_opflex: true
+ restrict_infra_vlan_traffic: true
+ opflex_ssl_versions: [ tls_v1.1, tls_v1.2 ]
+ check_mode: true
+ register: cm_update_fab_settings
+
+ - name: Update Fabric Wide Settings for ACI v5+
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_fab_settings_5
+ register: nm_update_fab_settings
+
+ - name: Update Fabric Wide Settings Again for ACI v5+
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_fab_settings_5
+ register: nm_update_fab_settings_again
+
+ - name: Verify Fabric Wide Settings for ACI v5+
+ ansible.builtin.assert:
+ that:
+ - cm_update_fab_settings is changed
+ - nm_update_fab_settings is changed
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.unicastXrEpLearnDisable == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.enforceSubnetCheck == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.validateOverlappingVlans == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.opflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.opflexpUseSsl == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.leafOpflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.leafOpflexpUseSsl == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.restrictInfraVLANTraffic == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.opflexpSslProtocols == "TLSv1.1,TLSv1.2"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.unicastXrEpLearnDisable == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.enforceSubnetCheck == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.validateOverlappingVlans == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.opflexpAuthenticateClients == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.opflexpUseSsl == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.leafOpflexpAuthenticateClients == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.leafOpflexpUseSsl == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.restrictInfraVLANTraffic == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.opflexpSslProtocols == "TLSv1.2"
+ - nm_update_fab_settings_again is not changed
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.unicastXrEpLearnDisable == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.enforceSubnetCheck == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.validateOverlappingVlans == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.opflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.opflexpUseSsl == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.leafOpflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.leafOpflexpUseSsl == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.restrictInfraVLANTraffic == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.opflexpSslProtocols == "TLSv1.1,TLSv1.2"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.unicastXrEpLearnDisable == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.enforceSubnetCheck == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.validateOverlappingVlans == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.opflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.opflexpUseSsl == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.leafOpflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.leafOpflexpUseSsl == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.restrictInfraVLANTraffic == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.opflexpSslProtocols == "TLSv1.1,TLSv1.2"
+
+ - name: Execute tests for ACI
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+ block:
+
+ - name: Update Fabric Wide Settings (check_mode)
+ cisco.aci.aci_fabric_wide_settings: &aci_fab_settings
+ <<: *aci_info
+ disable_remote_ep_learning: true
+ enforce_subnet_check: true
+ enforce_epg_vlan_validation: true
+ spine_opflex_client_auth: true
+ spine_ssl_opflex: true
+ check_mode: true
+ register: cm_update_fab_settings
+
+ - name: Update Fabric Wide Settings
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_fab_settings
+ register: nm_update_fab_settings
+
+ - name: Update Fabric Wide Settings Again
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_fab_settings
+ register: nm_update_fab_settings_again
+
+ - name: Verify Fabric Wide Settings
+ ansible.builtin.assert:
+ that:
+ - cm_update_fab_settings is changed
+ - nm_update_fab_settings is changed
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.unicastXrEpLearnDisable == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.enforceSubnetCheck == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.validateOverlappingVlans == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.opflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.opflexpUseSsl == "yes"
+ - nm_update_fab_settings.current.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.unicastXrEpLearnDisable == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.enforceSubnetCheck == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.validateOverlappingVlans == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.opflexpAuthenticateClients == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.opflexpUseSsl == "no"
+ - nm_update_fab_settings.previous.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+ - nm_update_fab_settings_again is not changed
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.unicastXrEpLearnDisable == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.enforceSubnetCheck == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.validateOverlappingVlans == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.opflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.opflexpUseSsl == "yes"
+ - nm_update_fab_settings_again.current.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.unicastXrEpLearnDisable == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.enforceSubnetCheck == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.validateOverlappingVlans == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.domainValidation == previous_settings.current.0.infraSetPol.attributes.domainValidation
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.opflexpAuthenticateClients == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.opflexpUseSsl == "yes"
+ - nm_update_fab_settings_again.previous.0.infraSetPol.attributes.reallocateGipo == previous_settings.current.0.infraSetPol.attributes.reallocateGipo
+
+ # QUERY FABRIC WIDE SETTINGS
+ - name: Query Fabric Wide Settings
+ cisco.aci.aci_fabric_wide_settings:
+ <<: *aci_info
+ state: query
+ register: query_fab
+
+ - name: Verify Fabric Wide Settings queries
+ ansible.builtin.assert:
+ that:
+ - query_fab is not changed
+ - query_fab.current.0.infraSetPol.attributes.unicastXrEpLearnDisable == "yes"
+ - query_fab.current.0.infraSetPol.attributes.enforceSubnetCheck == "yes"
+ - query_fab.current.0.infraSetPol.attributes.validateOverlappingVlans == "yes"
+ - query_fab.current.0.infraSetPol.attributes.domainValidation == query_fab.current.0.infraSetPol.attributes.domainValidation
+ - query_fab.current.0.infraSetPol.attributes.opflexpAuthenticateClients == "yes"
+ - query_fab.current.0.infraSetPol.attributes.opflexpUseSsl == "yes"
+ - query_fab.current.0.infraSetPol.attributes.reallocateGipo == query_fab.current.0.infraSetPol.attributes.reallocateGipo
+
+ - name: Verify Fabric Wide Settings queries
+ ansible.builtin.assert:
+ that:
+ - query_fab is not changed
+ - query_fab.current.0.infraSetPol.attributes.leafOpflexpAuthenticateClients == "yes"
+ - query_fab.current.0.infraSetPol.attributes.leafOpflexpUseSsl == "yes"
+ - query_fab.current.0.infraSetPol.attributes.restrictInfraVLANTraffic == "yes"
+ - query_fab.current.0.infraSetPol.attributes.opflexpSslProtocols == "TLSv1.1,TLSv1.2"
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/pki/rsa_ansible.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/pki/rsa_ansible.key
new file mode 100644
index 000000000..ac63a0055
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/pki/rsa_ansible.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDVyLS8/ix6QOH7R83B4WuhsliL6nffBvrkHXXsqViit3OZd+/K
+fSrNlZysUvHS4hxfRtJrFQfpkogwXEEupBPF3p0xy7wZzvjjWWJk0NQ8PoVlOhUY
+emZTfMX+FFNr9pAjjjaVHb9jCuxko7upAyj8POhhETY2zYoJoa8TR6fLZwIDAQAB
+AoGBALo5GzeGMThNTIyW/6Tjt94ifP9kPwcIDYSoJRECczNKmmgVEcxRO/fZW6DA
+n+YTEKPuDV059KqB+iAmPKFkS9N41kaq+NUAknlFJPV6Vs3gpvJGqWgu++73dhR5
+cKsHTlK2KBsRtsXnOJ9odKWFjiTnZ1Eyvmhw7ct+Fojb/7ABAkEA9+Wwm+HGlYqw
+ghuFaBtNuqC/S2vO6SEfdQvTDQKKO5ROei5m+ryjWj6flbCcG+5dLs8l4Zh3sQUL
+kc0RQfHSWQJBANzFkdO6wXXPOw7RhAEP2sA2W2VacMbGynjsoDJXmypeJ7Z+odLb
+5gNXET9RA77RY/saIBdwR4JNnku2WnoxU78CQQDhYirVP0vu8H6UfHMpeRGNqdLi
+vq0LlrrkDxEe1f1aN/e17HRiaZnXVfKABWeZmXmNMndNifLgtiaTtC+JllRZAkEA
+ydAdV0SANvaCETC7j9DzcgP+lm8PatYsHlCIvJxS7m71tKCbw0pbQDBmRtADMXrt
+/4vJTEPKSrYzfxiqKstOtwJAXkWXaqVhJeKjbMj1buo6s/1qGIfSrZR/AjozvJ03
+JehevfULS3668jOYJZW6BoNhysx6+Hqf5Id8fB4iDWPQhA==
+-----END RSA PRIVATE KEY-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml
new file mode 100644
index 000000000..ab1560ba6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_file_remote_path/tasks/main.yml
@@ -0,0 +1,231 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Tim Cragg (@timcragg)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_remote_path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: ansible_file_path
+ state: absent
+
+# CREATE FILE REMOTE PATH
+- name: Create a File Remote Path (check mode)
+ cisco.aci.aci_file_remote_path: &aci_path
+ <<: *aci_info
+ name: ansible_file_path
+ description: Test File Path
+ remote_host: test.example.com
+ remote_port: 22
+ remote_protocol: scp
+ remote_user: test_user
+ auth_type: password
+ remote_path: /tmp
+ check_mode: true
+ register: cm_create_path
+
+- name: Create a File Remote Path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_path
+ register: nm_create_path
+
+- name: Create a File Remote Path Again
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_path
+ register: nm_create_path_again
+
+- name: Create a second File Remote Path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: ansible_second_file_path
+ auth_type: password
+ remote_host: test2.example.com
+ remote_port: 22
+ remote_protocol: scp
+ remote_path: /tmp
+ management_epg: oob-default
+ register: create_second_path
+
+- name: Create File Remote Path using SSH Key auth
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: ansible_ssh_auth_file_path
+ auth_type: ssh_key
+ remote_key: "{{ lookup('file', 'pki/rsa_ansible.key') }}"
+ remote_host: test3.example.com
+ remote_port: 22
+ remote_protocol: scp
+ remote_path: /tmp
+ register: create_key_auth_path
+
+- name: Verify creation of File Remote Path
+ ansible.builtin.assert:
+ that:
+ - cm_create_path is changed
+ - nm_create_path is changed
+ - nm_create_path_again is not changed
+ - nm_create_path.current.0.fileRemotePath.attributes.name == "ansible_file_path"
+ - nm_create_path.current.0.fileRemotePath.attributes.descr == "Test File Path"
+ - nm_create_path.current.0.fileRemotePath.attributes.protocol == "scp"
+ - nm_create_path.current.0.fileRemotePath.attributes.remotePort == "22"
+ - nm_create_path.current.0.fileRemotePath.attributes.authType == "usePassword"
+ - nm_create_path.current.0.fileRemotePath.attributes.userName == "test_user"
+ - nm_create_path.current.0.fileRemotePath.attributes.remotePath == "/tmp"
+ - nm_create_path_again.current.0.fileRemotePath.attributes.name == "ansible_file_path"
+ - nm_create_path_again.current.0.fileRemotePath.attributes.descr == "Test File Path"
+ - nm_create_path_again.current.0.fileRemotePath.attributes.protocol == "scp"
+ - nm_create_path_again.current.0.fileRemotePath.attributes.remotePort == "22"
+ - nm_create_path_again.current.0.fileRemotePath.attributes.authType == "usePassword"
+ - nm_create_path_again.current.0.fileRemotePath.attributes.userName == "test_user"
+ - nm_create_path_again.current.0.fileRemotePath.attributes.remotePath == "/tmp"
+ - create_second_path.current.0.fileRemotePath.children.0.fileRsARemoteHostToEpg.attributes.tDn == "uni/tn-mgmt/mgmtp-default/oob-default"
+ - create_key_auth_path.current.0.fileRemotePath.attributes.authType == "useSshKeyContents"
+
+# UPDATE FILE REMOTE PATH
+- name: Update File Remote Path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_path
+ remote_protocol: sftp
+ remote_user: new_user
+ remote_password: new_pass
+ remote_path: /tmp/dummy
+ register: update_path
+
+- name: Verify update of File Remote Path
+ ansible.builtin.assert:
+ that:
+ - update_path is changed
+ - update_path.current.0.fileRemotePath.attributes.name == "ansible_file_path"
+ - update_path.current.0.fileRemotePath.attributes.descr == "Test File Path"
+ - update_path.current.0.fileRemotePath.attributes.protocol == "sftp"
+ - update_path.current.0.fileRemotePath.attributes.authType == "usePassword"
+ - update_path.current.0.fileRemotePath.attributes.userName == "new_user"
+ - update_path.current.0.fileRemotePath.attributes.remotePath == "/tmp/dummy"
+
+# QUERY FILE REMOTE PATH
+- name: Query a File Remote Path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_path
+ state: query
+ register: query_one
+
+- name: Query all File Remote Paths
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify File Remote Path queries
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current.0.fileRemotePath.attributes.name == "ansible_file_path"
+ - query_one.current.0.fileRemotePath.attributes.descr == "Test File Path"
+ - query_one.current.0.fileRemotePath.attributes.protocol == "sftp"
+ - query_one.current.0.fileRemotePath.attributes.authType == "usePassword"
+ - query_one.current.0.fileRemotePath.attributes.userName == "new_user"
+ - query_one.current.0.fileRemotePath.attributes.remotePath == "/tmp/dummy"
+ - query_all is not changed
+ - query_all.current | length > 1
+
+# VALIDATE ERROR CHECKING
+- name: Create Remote Path with remote_key when auth_type is password
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: incorrect_auth_type1
+ remote_host: test2.example.com
+ remote_port: 22
+ remote_protocol: scp
+ remote_user: test_user
+ auth_type: password
+ remote_key: "{{ lookup('file', 'pki/rsa_ansible.key') }}"
+ remote_path: /tmp
+ ignore_errors: true
+ register: incorrect_auth_type1
+
+- name: Create Remote Path with passphrase when auth_type is password
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: incorrect_auth_type2
+ remote_host: test2.example.com
+ remote_port: 22
+ remote_protocol: scp
+ remote_user: test_user
+ auth_type: password
+ passphrase: ansible_passphrase
+ remote_path: /tmp
+ ignore_errors: true
+ register: incorrect_auth_type2
+
+- name: Create Remote Path with password when auth_type is ssh_key
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: incorrect_auth_type3
+ remote_host: test2.example.com
+ remote_port: 22
+ remote_protocol: scp
+ remote_user: test_user
+ auth_type: ssh_key
+ remote_password: test_password
+ remote_path: /tmp
+ ignore_errors: true
+ register: incorrect_auth_type3
+
+- name: Validate error checking
+ ansible.builtin.assert:
+ that:
+ - incorrect_auth_type1 is failed
+ - incorrect_auth_type2 is failed
+ - incorrect_auth_type3 is failed
+ - incorrect_auth_type1.msg == "remote_key cannot be set if auth_type is password"
+ - incorrect_auth_type2.msg == "passphrase cannot be set if auth_type is password"
+ - incorrect_auth_type3.msg == "remote_password cannot be set if auth_type is ssh_key"
+
+# REMOVE FILE REMOTE PATH
+- name: Delete a File Remote Path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_path
+ state: absent
+ register: delete
+
+- name: Delete File Remote Path again
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_path
+ state: absent
+ register: delete_again
+
+- name: Verify deletion of File Remote Path
+ ansible.builtin.assert:
+ that:
+ - delete is changed
+ - delete_again is not changed
+ - delete.current == []
+
+- name: Delete Second File Remote Path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: ansible_second_file_path
+ state: absent
+
+- name: Delete SSH Key Auth File Remote Path
+ cisco.aci.aci_file_remote_path:
+ <<: *aci_info
+ name: ansible_ssh_auth_file_path
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml
index 77093a670..e969111a2 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml
@@ -20,296 +20,492 @@
use_proxy: '{{ aci_use_proxy | default(true) }}'
output_level: '{{ aci_output_level | default("debug") }}'
-- name: ensure tenant exists for tests to kick off
- cisco.aci.aci_tenant:
- <<: *aci_info
- tenant: ansible_test
- state: absent
-
-- name: ensure tenant exists for tests to kick off
- cisco.aci.aci_tenant: &aci_tenant_present
- <<: *aci_info
- tenant: ansible_test
- state: present
- register: tenant_present
-
-- name: ensure filter exists for tests to kick off
- cisco.aci.aci_filter: &aci_filter_present
- <<: *aci_tenant_present
- filter: anstest
- register: filter_present
-
-- name: create filter entry - check mode works
- cisco.aci.aci_filter_entry: &aci_entry_present
- <<: *aci_filter_present
- entry: anstest
- description: Ansible Test
- ether_type: ip
- ip_protocol: tcp
- dst_port_start: 80
- dst_port_end: 88
- check_mode: true
- register: entry_present_check_mode
-
-- name: create filter entry - creation works
- cisco.aci.aci_filter_entry:
- <<: *aci_entry_present
- register: entry_present
-
-- name: create filter entry - idempotency works
- cisco.aci.aci_filter_entry:
- <<: *aci_entry_present
- register: entry_present_idempotent
-
-- name: update filter entry - update works
- cisco.aci.aci_filter_entry:
- <<: *aci_entry_present
- description: Ansible Test Update
- dst_port_start: 80
- dst_port_end: 90
- register: entry_present_update
-
- name: Verify Cloud and Non-Cloud Sites in use.
include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
-- name: create filter entry - test different types
- cisco.aci.aci_filter_entry:
- <<: *aci_filter_present
- entry: anstest2
- ether_type: arp
- arp_flag: arp_reply
- register: entry_present_2
- when: query_cloud.current == [] # This condition will skip execution for cloud sites
-
-- name: create filter entry - test different types
- cisco.aci.aci_filter_entry:
- <<: *aci_filter_present
- entry: anstest3
- ether_type: ip
- ip_protocol: icmp
- icmp_msg_type: echo
- register: entry_present_3
-
-- name: create filter entry - test different types
- cisco.aci.aci_filter_entry:
- <<: *aci_filter_present
- entry: anstest4
- ether_type: ip
- ip_protocol: udp
- dst_port: 1000
- register: entry_present_4
-
-- name: missing param - failure message works
- cisco.aci.aci_filter_entry:
- <<: *aci_filter_present
- ignore_errors: true
- register: present_missing_param
-
-- name: incompatable params - failure message works
- cisco.aci.aci_filter_entry:
- <<: *aci_entry_present
- dst_port: 99
- ignore_errors: true
- register: present_incompatible_params
-
-- name: present assertions
- assert:
- that:
- - entry_present_check_mode is changed
- - entry_present_check_mode.previous == []
- - entry_present_check_mode.sent.vzEntry.attributes.dFromPort == 'http'
- - entry_present_check_mode.sent.vzEntry.attributes.dToPort == '88'
- - entry_present_check_mode.sent.vzEntry.attributes.descr == 'Ansible Test'
- - entry_present_check_mode.sent.vzEntry.attributes.etherT == 'ip'
- - entry_present_check_mode.sent.vzEntry.attributes.name == 'anstest'
- - entry_present_check_mode.sent.vzEntry.attributes.prot == 'tcp'
- - entry_present is changed
- - entry_present.current.0.vzEntry.attributes.annotation == 'orchestrator:ansible'
- - entry_present.previous == []
- - entry_present.sent == entry_present_check_mode.sent
- - entry_present_idempotent is not changed
- - entry_present_idempotent.previous != []
- - entry_present_idempotent.sent == {}
- - entry_present_update is changed
- - entry_present_update.previous != []
- - entry_present_update.sent != entry_present_update.proposed
- - entry_present_3 is changed
- - entry_present_3.sent.vzEntry.attributes.etherT == 'ip'
- - entry_present_3.sent.vzEntry.attributes.icmpv4T == 'echo'
- - entry_present_3.sent.vzEntry.attributes.name == 'anstest3'
- - entry_present_3.sent.vzEntry.attributes.prot == 'icmp'
- - entry_present_4 is changed
- - entry_present_4.sent.vzEntry.attributes.dFromPort == '1000'
- - entry_present_4.sent.vzEntry.attributes.dToPort == '1000'
- - entry_present_4.sent.vzEntry.attributes.etherT == 'ip'
- - entry_present_4.sent.vzEntry.attributes.name == 'anstest4'
- - entry_present_4.sent.vzEntry.attributes.prot == 'udp'
- - present_missing_param is failed
- - 'present_missing_param.msg == "state is present but all of the following are missing: entry"'
- - present_incompatible_params is failed
- - present_incompatible_params.msg.startswith("Parameter")
-
-- name: present assertions for arp
- assert:
- that:
- - entry_present_2 is changed
- - entry_present_2.sent.vzEntry.attributes.arpOpc == 'reply'
- - entry_present_2.sent.vzEntry.attributes.etherT == 'arp'
- - entry_present_2.sent.vzEntry.attributes.name == 'anstest2'
- when: query_cloud.current == [] # This condition will skip execution for cloud sites
-
-- name: query tenant filter entry
- cisco.aci.aci_filter_entry: &aci_query_entry
- <<: *aci_entry_present
- state: query
- register: query_tenant_filter_entry
-
-- name: query filter entry
- cisco.aci.aci_filter_entry:
- <<: *aci_query_entry
- tenant: "{{ fakevar | default(omit) }}"
- register: query_filter_entry
-
-- name: query tenant entry
- cisco.aci.aci_filter_entry:
- <<: *aci_query_entry
- filter: "{{ fakevar | default(omit) }}"
- register: query_tenant_entry
-
-- name: query tenant filter
- cisco.aci.aci_filter_entry:
- <<: *aci_query_entry
- entry: "{{ fakevar | default(omit) }}"
- register: query_tenant_filter
-
-- name: query entry
- cisco.aci.aci_filter_entry: &aci_query_entry_2
- <<: *aci_query_entry
- tenant: "{{ fakevar | default(omit) }}"
- filter: "{{ fakevar | default(omit) }}"
- register: query_entry
-
-- name: query filter
- cisco.aci.aci_filter_entry:
- <<: *aci_query_entry
- tenant: "{{ fakevar | default(omit) }}"
- entry: "{{ fakevar | default(omit) }}"
- register: query_filter
-
-- name: query tenant
- cisco.aci.aci_filter_entry:
- <<: *aci_query_entry
- filter: "{{ fakevar | default(omit) }}"
- entry: "{{ fakevar | default(omit) }}"
- register: query_tenant
-
-- name: query all
- cisco.aci.aci_filter_entry:
- <<: *aci_query_entry_2
- entry: "{{ fakevar | default(omit) }}"
- register: query_all
-
-- name: query assertions for all
- assert:
- that:
- - query_tenant_filter_entry is not changed
- - query_tenant_filter_entry.current | length == 1
- - query_tenant_filter_entry.current.0.vzEntry.attributes.name == "anstest"
- - '"tn-ansible_test/flt-anstest/e-anstest.json" in query_tenant_filter_entry.url'
- - query_filter_entry is not changed
- - query_filter_entry.current.0.vzFilter.attributes.name == "anstest"
- - query_filter_entry.current.0.vzFilter.children | length == 1
- - '"query-target-filter=eq(vzFilter.name,\"anstest\")" in query_filter_entry.filter_string'
- - '"rsp-subtree-filter=eq(vzEntry.name,\"anstest\")" in query_filter_entry.filter_string'
- - '"class/vzFilter.json" in query_filter_entry.url'
- - query_tenant_entry is not changed
- - query_tenant_entry.current | length == 1
- - query_tenant_entry.current.0.fvTenant.attributes.name == "ansible_test"
- - '"rsp-subtree-filter=eq(vzEntry.name,\"anstest\")" in query_tenant_entry.filter_string'
- - '"rsp-subtree-class=vzEntry" in query_tenant_entry.filter_string'
- - '"tn-ansible_test.json" in query_tenant_entry.url'
- - query_tenant_filter is not changed
- - query_tenant_filter.current | length == 1
- - query_tenant_filter.current.0.vzFilter.attributes.name == "anstest"
- - '"rsp-subtree-class=vzEntry" in query_tenant_filter.filter_string'
- - '"tn-ansible_test/flt-anstest.json" in query_tenant_filter.url'
- - query_entry is not changed
- - query_entry.current.0.vzEntry.attributes.name == "anstest"
- - '"query-target-filter=eq(vzEntry.name,\"anstest\")" in query_entry.filter_string'
- - '"class/vzEntry.json" in query_entry.url'
- - query_filter is not changed
- - query_filter.current.0.vzFilter.attributes.name == "anstest"
- - '"query-target-filter=eq(vzFilter.name,\"anstest\")" in query_filter.filter_string'
- - '"rsp-subtree-class=vzEntry" in query_filter.filter_string'
- - '"class/vzFilter.json" in query_filter.url'
- - query_tenant is not changed
- - query_tenant.current | length == 1
- - query_tenant.current.0.fvTenant.attributes.name == "ansible_test"
- - '"rsp-subtree-class=vzEntry,vzFilter" in query_tenant.filter_string'
- - '"tn-ansible_test.json" in query_tenant.url'
- - query_all is not changed
- - query_all.current | length > 1
- - query_all.current.0.vzEntry is defined
- - '"class/vzEntry.json" in query_all.url'
-
-
-- name: query assertions for only Non-Cloud
- assert:
- that:
- - query_tenant_filter.current.0.vzFilter.children | length == 4
- when: query_cloud.current == [] # This condition will skip execution for cloud sites
-
-- name: delete entry - check mode works
- cisco.aci.aci_filter_entry: &aci_entry_absent
- <<: *aci_entry_present
- state: absent
- check_mode: true
- register: entry_absent_check_mode
-
-- name: delete entry - deletion works
- cisco.aci.aci_filter_entry:
- <<: *aci_entry_absent
- register: entry_absent
-
-- name: delete entry - idempotency works
- cisco.aci.aci_filter_entry:
- <<: *aci_entry_absent
- register: entry_absent_idempotent
-
-- name: missing param - failure message works
- cisco.aci.aci_filter_entry:
- <<: *aci_tenant_present
- state: absent
- ignore_errors: true
- register: absent_missing_param
-
-- name: cleanup remaining entries
- cisco.aci.aci_filter_entry:
- <<: *aci_entry_absent
- entry: "{{ item }}"
- with_items: ["anstest2", "anstest3", "anstest4"]
-
-- name: absent assertions
- assert:
- that:
- - entry_absent_check_mode is changed
- - entry_absent_check_mode.previous != []
- - entry_absent is changed
- - entry_absent.previous == entry_absent_check_mode.previous
- - entry_absent.proposed == {}
- - entry_absent_idempotent is not changed
- - entry_absent_idempotent.previous == []
- - absent_missing_param is failed
- - 'absent_missing_param.msg == "state is absent but all of the following are missing: entry, filter"'
-
-- name: cleanup filter
- cisco.aci.aci_filter:
- <<: *aci_filter_present
- state: absent
- when: filter_present is changed
-
-- name: cleanup tenant
- cisco.aci.aci_tenant:
- <<: *aci_tenant_present
- state: absent
- when: tenant_present is changed
+# TODO current module will fail on cloud sites because range is not supported
+# APIC Error 1: Invalid Configuration CLOUD_SOURCE_PORT_NOT_SUPPORTED: vz::EntryMo Dn = uni/tn-ansible_test/flt-anstest_fileter_2/e-source_port_start - Source port range is not allowed on CAPIC"
+- 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_info
+ tenant: ansible_test
+ state: absent
+
+ - name: ensure tenant exists for tests to kick off
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+ register: tenant_present
+
+ - name: ensure filter exists for tests to kick off
+ cisco.aci.aci_filter: &aci_filter_present
+ <<: *aci_tenant_present
+ filter: anstest
+ register: filter_present
+
+ - name: ensure anstest_2 filter exists for tests to kick off
+ cisco.aci.aci_filter: &anstest_fileter_2_present
+ <<: *aci_tenant_present
+ filter: anstest_fileter_2
+
+ - name: Create a filter entry with the match_only_fragments - enabled and dst_port values - negative test
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: nt_match_only_fragments_with_dst_port
+ ether_type: ip
+ ip_protocol: tcp
+ dst_port_start: 80
+ dst_port_end: 88
+ match_only_fragments: true
+ register: nt_match_only_fragments_with_dst_port
+ ignore_errors: true
+
+ - name: Create a filter entry with the match_only_fragments - enabled
+ cisco.aci.aci_filter_entry: &match_only_fragments_enabled
+ <<: *anstest_fileter_2_present
+ entry: match_only_fragments_enabled
+ ether_type: ip
+ ip_protocol: tcp
+ match_only_fragments: true
+ register: match_only_fragments_enabled
+
+ - name: Disabled the match_only_fragments of an existing filter entry - "match_only_fragments_enabled"
+ cisco.aci.aci_filter_entry:
+ <<: *match_only_fragments_enabled
+ match_only_fragments: false
+ register: match_only_fragments_disabled
+
+ - name: Create a filter entry with the source_port values - negative test
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: nt_source_port
+ ether_type: ip
+ ip_protocol: tcp
+ source_port: 20
+ source_port_start: 22
+ source_port_end: 22
+ register: nt_source_port
+ ignore_errors: true
+
+ - name: Create a filter entry with the only dst_port_end - negative test
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: nt_dst_port_end
+ ether_type: ip
+ ip_protocol: tcp
+ dst_port_end: 20
+ register: nt_dst_port_end
+ ignore_errors: true
+
+ - name: Create a filter entry with the only source_port_end - negative test
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: nt_source_port_end
+ ether_type: ip
+ ip_protocol: tcp
+ source_port_end: 20
+ register: nt_source_port_end
+ ignore_errors: true
+
+ - name: Create a filter entry with the only source_port_start
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: source_port_start
+ ether_type: ip
+ ip_protocol: tcp
+ source_port_start: 20
+ register: source_port_start
+
+ - name: Create a filter entry with only source_port_start, source_port_end and valid tcp_flags rules
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: source_port_values
+ ether_type: ip
+ ip_protocol: tcp
+ source_port_start: 20
+ source_port_end: 23
+ tcp_flags:
+ - acknowledgment
+ - finish
+ register: source_port_values
+
+ - name: Updated source port and tcp_flags values of an existing filter entry - "source_port_values"
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: source_port_values
+ ether_type: ip
+ ip_protocol: tcp
+ source_port: 53
+ tcp_flags:
+ - acknowledgment
+ register: update_source_port_values
+
+ - name: Create a filter entry with the tcp_flags - established and other tcp rules - negative test
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: nt_tcp_flags
+ ether_type: ip
+ ip_protocol: tcp
+ tcp_flags:
+ - acknowledgment
+ - established
+ - finish
+ register: nt_tcp_flags
+ ignore_errors: true
+
+ - name: Create a filter entry with the tcp_flags - established
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: tcp_flags_est
+ ether_type: ip
+ ip_protocol: tcp
+ tcp_flags:
+ - established
+ register: tcp_flags_est
+
+ - name: Create a filter entry with icmp6_msg_type - established
+ cisco.aci.aci_filter_entry:
+ <<: *anstest_fileter_2_present
+ entry: icmp6_msg_type_est
+ icmp6_msg_type: neighbor_solicitation
+ register: icmp6_msg_type_est
+
+ - name: Assertion check for the filter entry - match_only_fragments, source_port and tcp_flags attributes
+ assert:
+ that:
+ - nt_match_only_fragments_with_dst_port is not changed
+ - nt_match_only_fragments_with_dst_port.msg == "Parameter 'match_only_fragments' cannot be used with 'Layer 4 Port' value"
+ - match_only_fragments_enabled is changed
+ - match_only_fragments_enabled.current.0.vzEntry.attributes.name == "match_only_fragments_enabled"
+ - match_only_fragments_enabled.current.0.vzEntry.attributes.tcpRules == match_only_fragments_enabled.current.0.vzEntry.attributes.tcpRules == ""
+ - match_only_fragments_enabled.current.0.vzEntry.attributes.applyToFrag == match_only_fragments_enabled.sent.vzEntry.attributes.applyToFrag == "yes"
+ - match_only_fragments_enabled.current.0.vzEntry.attributes.sFromPort == match_only_fragments_enabled.current.0.vzEntry.attributes.sToPort == "unspecified"
+ - match_only_fragments_enabled.current.0.vzEntry.attributes.dFromPort == match_only_fragments_enabled.current.0.vzEntry.attributes.dToPort == "unspecified"
+ - match_only_fragments_disabled is changed
+ - match_only_fragments_disabled.current.0.vzEntry.attributes.applyToFrag == match_only_fragments_disabled.sent.vzEntry.attributes.applyToFrag == "no"
+ - match_only_fragments_disabled.current.0.vzEntry.attributes.name == "match_only_fragments_enabled"
+ - match_only_fragments_disabled.current.0.vzEntry.attributes.tcpRules == ""
+ - match_only_fragments_disabled.current.0.vzEntry.attributes.sFromPort == match_only_fragments_disabled.current.0.vzEntry.attributes.sToPort == "unspecified"
+ - match_only_fragments_disabled.current.0.vzEntry.attributes.dFromPort == match_only_fragments_disabled.current.0.vzEntry.attributes.dToPort == "unspecified"
+ - nt_source_port is not changed
+ - nt_source_port.msg == "Parameter 'source_port' cannot be used with 'source_port_end' and 'source_port_start'"
+ - nt_dst_port_end is not changed
+ - nt_dst_port_end.msg == "Parameter 'dst_port_end' cannot be configured when the 'dst_port_start' is not defined"
+ - nt_source_port_end is not changed
+ - nt_source_port_end.msg == "Parameter 'source_port_end' cannot be configured when the 'source_port_start' is not defined"
+ - source_port_start is changed
+ - source_port_start.current.0.vzEntry.attributes.name == source_port_start.sent.vzEntry.attributes.name == "source_port_start"
+ - source_port_start.current.0.vzEntry.attributes.sFromPort == source_port_start.sent.vzEntry.attributes.sFromPort == "ftpData"
+ - source_port_start.current.0.vzEntry.attributes.sToPort == "ftpData"
+ - source_port_start.current.0.vzEntry.attributes.tcpRules == source_port_start.sent.vzEntry.attributes.tcpRules == ""
+ - source_port_start.current.0.vzEntry.attributes.applyToFrag == "no"
+ - source_port_start.current.0.vzEntry.attributes.arpOpc == "unspecified"
+ - source_port_start.current.0.vzEntry.attributes.etherT == "ip"
+ - source_port_start.current.0.vzEntry.attributes.prot == "tcp"
+ - source_port_values is changed
+ - source_port_values.current.0.vzEntry.attributes.name == source_port_values.sent.vzEntry.attributes.name == "source_port_values"
+ - source_port_values.current.0.vzEntry.attributes.sFromPort == source_port_values.sent.vzEntry.attributes.sFromPort == "ftpData"
+ - source_port_values.current.0.vzEntry.attributes.sToPort == source_port_values.sent.vzEntry.attributes.sToPort == "23"
+ - source_port_values.current.0.vzEntry.attributes.tcpRules == source_port_values.sent.vzEntry.attributes.tcpRules == "ack,fin"
+ - source_port_values.current.0.vzEntry.attributes.applyToFrag == "no"
+ - source_port_values.current.0.vzEntry.attributes.arpOpc == "unspecified"
+ - source_port_values.current.0.vzEntry.attributes.etherT == "ip"
+ - source_port_values.current.0.vzEntry.attributes.prot == "tcp"
+ - update_source_port_values is changed
+ - update_source_port_values.current.0.vzEntry.attributes.name == "source_port_values"
+ - update_source_port_values.current.0.vzEntry.attributes.applyToFrag == "no"
+ - update_source_port_values.current.0.vzEntry.attributes.arpOpc == "unspecified"
+ - update_source_port_values.current.0.vzEntry.attributes.etherT == "ip"
+ - update_source_port_values.current.0.vzEntry.attributes.prot == "tcp"
+ - update_source_port_values.current.0.vzEntry.attributes.sFromPort == update_source_port_values.sent.vzEntry.attributes.sFromPort == "dns"
+ - update_source_port_values.current.0.vzEntry.attributes.sToPort == update_source_port_values.sent.vzEntry.attributes.sToPort == "dns"
+ - update_source_port_values.current.0.vzEntry.attributes.tcpRules == update_source_port_values.sent.vzEntry.attributes.tcpRules == "ack"
+ - nt_tcp_flags is not changed
+ - nt_tcp_flags.msg == "TCP established cannot be combined with other tcp rules"
+ - tcp_flags_est is changed
+ - tcp_flags_est.current.0.vzEntry.attributes.applyToFrag == "no"
+ - tcp_flags_est.current.0.vzEntry.attributes.tcpRules == tcp_flags_est.sent.vzEntry.attributes.tcpRules == "est"
+ - tcp_flags_est.current.0.vzEntry.attributes.name == tcp_flags_est.sent.vzEntry.attributes.name == "tcp_flags_est"
+ - tcp_flags_est.current.0.vzEntry.attributes.etherT == tcp_flags_est.sent.vzEntry.attributes.etherT == "ip"
+ - icmp6_msg_type_est.current.0.vzEntry.attributes.icmpv6T == "nbr-solicit"
+
+ - name: create filter entry - check mode works
+ cisco.aci.aci_filter_entry: &aci_entry_present
+ <<: *aci_filter_present
+ entry: anstest
+ description: Ansible Test
+ ether_type: ip
+ ip_protocol: tcp
+ dst_port_start: 80
+ dst_port_end: 88
+ check_mode: true
+ register: entry_present_check_mode
+
+ - name: create filter entry - creation works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_present
+ register: entry_present
+
+ - name: create filter entry - idempotency works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_present
+ register: entry_present_idempotent
+
+ - name: update filter entry - update works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_present
+ description: Ansible Test Update
+ dst_port: 80
+ dst_port_start: "{{ fake_var | default(omit) }}"
+ dst_port_end: "{{ fake_var | default(omit) }}"
+ register: entry_present_update
+
+ - name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+ - name: create filter entry - test different types
+ cisco.aci.aci_filter_entry:
+ <<: *aci_filter_present
+ entry: anstest2
+ ether_type: arp
+ arp_flag: arp_reply
+ register: entry_present_2
+ when: query_cloud.current == [] # This condition will skip execution for cloud sites
+
+ - name: create filter entry - test different types
+ cisco.aci.aci_filter_entry:
+ <<: *aci_filter_present
+ entry: anstest3
+ ether_type: ip
+ ip_protocol: icmp
+ icmp_msg_type: echo
+ register: entry_present_3
+
+ - name: create filter entry - test different types
+ cisco.aci.aci_filter_entry:
+ <<: *aci_filter_present
+ entry: anstest4
+ ether_type: ip
+ ip_protocol: udp
+ dst_port: 1000
+ register: entry_present_4
+
+ - name: missing param - failure message works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_filter_present
+ ignore_errors: true
+ register: present_missing_param
+
+ - name: incompatable params - failure message works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_present
+ dst_port: 99
+ ignore_errors: true
+ register: present_incompatible_params
+
+ - name: present assertions
+ assert:
+ that:
+ - entry_present_check_mode is changed
+ - entry_present_check_mode.previous == []
+ - entry_present_check_mode.sent.vzEntry.attributes.dFromPort == 'http'
+ - entry_present_check_mode.sent.vzEntry.attributes.dToPort == '88'
+ - entry_present_check_mode.sent.vzEntry.attributes.descr == 'Ansible Test'
+ - entry_present_check_mode.sent.vzEntry.attributes.etherT == 'ip'
+ - entry_present_check_mode.sent.vzEntry.attributes.name == 'anstest'
+ - entry_present_check_mode.sent.vzEntry.attributes.prot == 'tcp'
+ - entry_present is changed
+ - entry_present.current.0.vzEntry.attributes.annotation == 'orchestrator:ansible'
+ - entry_present.previous == []
+ - entry_present.sent == entry_present_check_mode.sent
+ - entry_present_idempotent is not changed
+ - entry_present_idempotent.previous != []
+ - entry_present_idempotent.sent == {}
+ - entry_present_update is changed
+ - entry_present_update.previous != []
+ - entry_present_update.sent != entry_present_update.proposed
+ - entry_present_3 is changed
+ - entry_present_3.sent.vzEntry.attributes.etherT == 'ip'
+ - entry_present_3.sent.vzEntry.attributes.icmpv4T == 'echo'
+ - entry_present_3.sent.vzEntry.attributes.name == 'anstest3'
+ - entry_present_3.sent.vzEntry.attributes.prot == 'icmp'
+ - entry_present_4 is changed
+ - entry_present_4.sent.vzEntry.attributes.dFromPort == '1000'
+ - entry_present_4.sent.vzEntry.attributes.dToPort == '1000'
+ - entry_present_4.sent.vzEntry.attributes.etherT == 'ip'
+ - entry_present_4.sent.vzEntry.attributes.name == 'anstest4'
+ - entry_present_4.sent.vzEntry.attributes.prot == 'udp'
+ - present_missing_param is failed
+ - 'present_missing_param.msg == "state is present but all of the following are missing: entry"'
+ - present_incompatible_params is failed
+ - present_incompatible_params.msg.startswith("Parameter")
+
+ - name: present assertions for arp
+ assert:
+ that:
+ - entry_present_2 is changed
+ - entry_present_2.sent.vzEntry.attributes.arpOpc == 'reply'
+ - entry_present_2.sent.vzEntry.attributes.etherT == 'arp'
+ - entry_present_2.sent.vzEntry.attributes.name == 'anstest2'
+ when: query_cloud.current == [] # This condition will skip execution for cloud sites
+
+ - name: query tenant filter entry
+ cisco.aci.aci_filter_entry: &aci_query_entry
+ <<: *aci_entry_present
+ state: query
+ register: query_tenant_filter_entry
+
+ - name: query filter entry
+ cisco.aci.aci_filter_entry:
+ <<: *aci_query_entry
+ tenant: "{{ fakevar | default(omit) }}"
+ register: query_filter_entry
+
+ - name: query tenant entry
+ cisco.aci.aci_filter_entry:
+ <<: *aci_query_entry
+ filter: "{{ fakevar | default(omit) }}"
+ register: query_tenant_entry
+
+ - name: query tenant filter
+ cisco.aci.aci_filter_entry:
+ <<: *aci_query_entry
+ entry: "{{ fakevar | default(omit) }}"
+ register: query_tenant_filter
+
+ - name: query entry
+ cisco.aci.aci_filter_entry: &aci_query_entry_2
+ <<: *aci_query_entry
+ tenant: "{{ fakevar | default(omit) }}"
+ filter: "{{ fakevar | default(omit) }}"
+ register: query_entry
+
+ - name: query filter
+ cisco.aci.aci_filter_entry:
+ <<: *aci_query_entry
+ tenant: "{{ fakevar | default(omit) }}"
+ entry: "{{ fakevar | default(omit) }}"
+ register: query_filter
+
+ - name: query tenant
+ cisco.aci.aci_filter_entry:
+ <<: *aci_query_entry
+ filter: "{{ fakevar | default(omit) }}"
+ entry: "{{ fakevar | default(omit) }}"
+ register: query_tenant
+
+ - name: query all
+ cisco.aci.aci_filter_entry:
+ <<: *aci_query_entry_2
+ entry: "{{ fakevar | default(omit) }}"
+ register: query_all
+
+ - name: query assertions for all
+ assert:
+ that:
+ - query_tenant_filter_entry is not changed
+ - query_tenant_filter_entry.current | length == 1
+ - query_tenant_filter_entry.current.0.vzEntry.attributes.name == "anstest"
+ - '"tn-ansible_test/flt-anstest/e-anstest.json" in query_tenant_filter_entry.url'
+ - query_filter_entry is not changed
+ - query_filter_entry.current.0.vzFilter.attributes.name == "anstest"
+ - query_filter_entry.current.0.vzFilter.children | length == 1
+ - '"query-target-filter=eq(vzFilter.name,\"anstest\")" in query_filter_entry.filter_string'
+ - '"rsp-subtree-filter=eq(vzEntry.name,\"anstest\")" in query_filter_entry.filter_string'
+ - '"class/vzFilter.json" in query_filter_entry.url'
+ - query_tenant_entry is not changed
+ - query_tenant_entry.current | length == 1
+ - query_tenant_entry.current.0.fvTenant.attributes.name == "ansible_test"
+ - '"rsp-subtree-filter=eq(vzEntry.name,\"anstest\")" in query_tenant_entry.filter_string'
+ - '"rsp-subtree-class=vzEntry" in query_tenant_entry.filter_string'
+ - '"tn-ansible_test.json" in query_tenant_entry.url'
+ - query_tenant_filter is not changed
+ - query_tenant_filter.current | length == 1
+ - query_tenant_filter.current.0.vzFilter.attributes.name == "anstest"
+ - '"rsp-subtree-class=vzEntry" in query_tenant_filter.filter_string'
+ - '"tn-ansible_test/flt-anstest.json" in query_tenant_filter.url'
+ - query_entry is not changed
+ - query_entry.current.0.vzEntry.attributes.name == "anstest"
+ - '"query-target-filter=eq(vzEntry.name,\"anstest\")" in query_entry.filter_string'
+ - '"class/vzEntry.json" in query_entry.url'
+ - query_filter is not changed
+ - query_filter.current.0.vzFilter.attributes.name == "anstest"
+ - '"query-target-filter=eq(vzFilter.name,\"anstest\")" in query_filter.filter_string'
+ - '"rsp-subtree-class=vzEntry" in query_filter.filter_string'
+ - '"class/vzFilter.json" in query_filter.url'
+ - query_tenant is not changed
+ - query_tenant.current | length == 1
+ - query_tenant.current.0.fvTenant.attributes.name == "ansible_test"
+ - '"rsp-subtree-class=vzEntry,vzFilter" in query_tenant.filter_string'
+ - '"tn-ansible_test.json" in query_tenant.url'
+ - query_all is not changed
+ - query_all.current | length > 1
+ - query_all.current.0.vzEntry is defined
+ - '"class/vzEntry.json" in query_all.url'
+
+
+ - name: query assertions for only Non-Cloud
+ assert:
+ that:
+ - query_tenant_filter.current.0.vzFilter.children | length == 4
+ when: query_cloud.current == [] # This condition will skip execution for cloud sites
+
+ - name: delete entry - check mode works
+ cisco.aci.aci_filter_entry: &aci_entry_absent
+ <<: *aci_entry_present
+ state: absent
+ check_mode: true
+ register: entry_absent_check_mode
+
+ - name: delete entry - deletion works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_absent
+ register: entry_absent
+
+ - name: delete entry - idempotency works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_absent
+ register: entry_absent_idempotent
+
+ - name: missing param - failure message works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_tenant_present
+ state: absent
+ ignore_errors: true
+ register: absent_missing_param
+
+ - name: cleanup remaining entries
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_absent
+ entry: "{{ item }}"
+ with_items: ["anstest2", "anstest3", "anstest4"]
+
+ - name: absent assertions
+ assert:
+ that:
+ - entry_absent_check_mode is changed
+ - entry_absent_check_mode.previous != []
+ - entry_absent is changed
+ - entry_absent.previous == entry_absent_check_mode.previous
+ - entry_absent.proposed == {}
+ - entry_absent_idempotent is not changed
+ - entry_absent_idempotent.previous == []
+ - absent_missing_param is failed
+ - 'absent_missing_param.msg == "state is absent but all of the following are missing: entry, filter"'
+
+ - name: cleanup filter
+ cisco.aci.aci_filter:
+ <<: *aci_filter_present
+ state: absent
+ when: filter_present is changed
+
+ - name: cleanup tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present is changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml
new file mode 100644
index 000000000..5cf88997c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group/tasks/main.yml
@@ -0,0 +1,154 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Create firmware policy
+ aci_firmware_policy: &aci_firmware_policy_present
+ <<: *aci_info
+ name: anstest_policy
+ version: n9000-15.2(7)
+ state: present
+
+ - name: Ensure first firmware group does not exist
+ aci_firmware_group: &aci_firmware_group_absent
+ <<: *aci_info
+ group: anstest_group
+ policy: anstest_policy
+ type_group: all
+ description: test firmware group
+ state: absent
+
+ - name: Ensure second firmware group does not exist
+ aci_firmware_group: &aci_firmware_group_2_absent
+ <<: *aci_info
+ group: anstest_group_2
+ policy: anstest_policy
+ state: absent
+
+ - name: Create first firmware group (check_mode)
+ aci_firmware_group: &aci_firmware_group_present
+ <<: *aci_firmware_group_absent
+ state: present
+ check_mode: true
+ register: cm_add_firmware_group_1
+
+ - name: Create first firmware group (normal_mode)
+ aci_firmware_group:
+ <<: *aci_firmware_group_present
+ register: nm_add_firmware_group_1
+
+ - name: Create first firmware group again - testing idempotency
+ aci_firmware_group:
+ <<: *aci_firmware_group_present
+ register: idempotency_add_firmware_group_1
+
+ - name: Create second firmware group
+ aci_firmware_group: &aci_firmware_group_2_present
+ <<: *aci_firmware_group_2_absent
+ state: present
+ register: nm_add_firmware_group_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_firmware_group_1 is changed
+ - cm_add_firmware_group_1.previous == []
+ - cm_add_firmware_group_1.current == []
+ - nm_add_firmware_group_1 is changed
+ - nm_add_firmware_group_1.current.0.firmwareFwGrp.attributes.name == "anstest_group"
+ - nm_add_firmware_group_1.current.0.firmwareFwGrp.attributes.type == "ALL"
+ - nm_add_firmware_group_1.current.0.firmwareFwGrp.children.0.firmwareRsFwgrpp.attributes.tnFirmwareFwPName == "anstest_policy"
+ - idempotency_add_firmware_group_1 is not changed
+ - nm_add_firmware_group_2 is changed
+
+ - name: Query all firmware groups
+ aci_firmware_group:
+ <<: *aci_info
+ state: query
+ register: query_all_firmware_group
+
+ - name: Query first firmware group
+ aci_firmware_group:
+ <<: *aci_firmware_group_present
+ state: query
+ register: query_first_firmware_group
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_firmware_group is not changed
+ - query_all_firmware_group.current | length >= 2
+ - '"firmwareRsFwgrpp" in query_all_firmware_group.filter_string'
+ - '"class/firmwareFwGrp.json" in query_all_firmware_group.url'
+ - query_first_firmware_group is not changed
+ - query_first_firmware_group.current.0.firmwareFwGrp.attributes.name == "anstest_group"
+ - query_first_firmware_group.current.0.firmwareFwGrp.attributes.type == "ALL"
+ - query_first_firmware_group.current.0.firmwareFwGrp.children.0.firmwareRsFwgrpp.attributes.tnFirmwareFwPName == "anstest_policy"
+
+ - name: Delete first firmware group (check_mode)
+ aci_firmware_group:
+ <<: *aci_firmware_group_present
+ state: absent
+ check_mode: true
+ register: cm_delete_firmware_group_1
+
+ - name: Delete first firmware group (normal_mode)
+ aci_firmware_group:
+ <<: *aci_firmware_group_present
+ state: absent
+ register: nm_delete_firmware_group_1
+
+ - name: Delete first firmware group again - testing idempotency
+ aci_firmware_group:
+ <<: *aci_firmware_group_present
+ state: absent
+ register: idempotency_delete_firmware_group_1
+
+ - name: Delete second firmware group (normal_mode)
+ aci_firmware_group:
+ <<: *aci_firmware_group_2_present
+ state: absent
+ register: nm_delete_firmware_group_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_firmware_group_1 is changed
+ - cm_delete_firmware_group_1.proposed == {}
+ - nm_delete_firmware_group_1 is changed
+ - nm_delete_firmware_group_1.previous != []
+ - nm_delete_firmware_group_1.current == []
+ - idempotency_delete_firmware_group_1 is not changed
+ - idempotency_delete_firmware_group_1.previous == []
+ - nm_delete_firmware_group_2 is changed
+ - nm_delete_firmware_group_2.previous != []
+ - nm_delete_firmware_group_2.current == []
+
+ - name: Delete firmware policy - clean up the environment
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml
new file mode 100644
index 000000000..8da20a7ca
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_group_node/tasks/main.yml
@@ -0,0 +1,164 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Create firmware policy exists
+ aci_firmware_policy: &aci_firmware_policy_present
+ <<: *aci_info
+ name: anstest_policy
+ version: n9000-15.2(7)
+ state: present
+
+ - name: Create first firmware group
+ aci_firmware_group: &aci_firmware_group_present
+ <<: *aci_info
+ group: anstest_group
+ firmwarepol: anstest_policy
+ state: present
+
+ - name: Ensure first firmware group node does not exist
+ aci_firmware_group_node: &aci_firmware_group_node_absent
+ <<: *aci_info
+ group: anstest_group
+ node: 1001
+ state: absent
+
+ - name: Ensure second firmware group node does not exist
+ aci_firmware_group_node: &aci_firmware_group_node_2_absent
+ <<: *aci_info
+ group: anstest_group
+ node: 1002
+ state: absent
+
+ - name: Create first firmware group node (check_mode)
+ aci_firmware_group_node: &aci_firmware_group_node_present
+ <<: *aci_firmware_group_node_absent
+ state: present
+ check_mode: true
+ register: cm_add_firmware_group_node_1
+
+ - name: Create first firmware group node (normal_mode)
+ aci_firmware_group_node:
+ <<: *aci_firmware_group_node_present
+ register: nm_add_firmware_group_node_1
+
+ - name: Create first firmware group node again - testing idempotency
+ aci_firmware_group_node:
+ <<: *aci_firmware_group_node_present
+ register: idempotency_add_firmware_group_node_1
+
+ - name: Create second firmware group node
+ aci_firmware_group_node: &aci_firmware_group_node_2_present
+ <<: *aci_firmware_group_node_2_absent
+ state: present
+ register: nm_add_firmware_group_node_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_firmware_group_node_1 is changed
+ - cm_add_firmware_group_node_1.previous == []
+ - cm_add_firmware_group_node_1.current == []
+ - nm_add_firmware_group_node_1 is changed
+ - nm_add_firmware_group_node_1.current.0.fabricNodeBlk.attributes.from_ == "1001"
+ - nm_add_firmware_group_node_1.current.0.fabricNodeBlk.attributes.to_ == "1001"
+ - idempotency_add_firmware_group_node_1 is not changed
+ - nm_add_firmware_group_node_2 is changed
+ - nm_add_firmware_group_node_2.current.0.fabricNodeBlk.attributes.from_ == "1002"
+ - nm_add_firmware_group_node_2.current.0.fabricNodeBlk.attributes.to_ == "1002"
+
+
+ - name: Query all firmware group nodes
+ aci_firmware_group_node:
+ <<: *aci_info
+ state: query
+ register: query_all_firmware_group_node
+
+ - name: Query first firmware group nnode
+ aci_firmware_group_node:
+ <<: *aci_firmware_group_node_present
+ state: query
+ register: query_first_firmware_group_node
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_firmware_group_node is not changed
+ - query_all_firmware_group_node.current | length >= 2
+ - '"class/fabricNodeBlk.json" in query_all_firmware_group_node.url'
+ - query_first_firmware_group_node is not changed
+ - query_first_firmware_group_node.current.0.fabricNodeBlk.attributes.from_ == "1001"
+ - query_first_firmware_group_node.current.0.fabricNodeBlk.attributes.to_ == "1001"
+
+ - name: Delete first firmware group (check_mode)
+ aci_firmware_group_node:
+ <<: *aci_firmware_group_node_present
+ state: absent
+ check_mode: true
+ register: cm_delete_firmware_group_node_1
+
+ - name: Delete first firmware group (normal_mode)
+ aci_firmware_group_node:
+ <<: *aci_firmware_group_node_present
+ state: absent
+ register: nm_delete_firmware_group_node_1
+
+ - name: Delete first firmware group again - testing idempotency
+ aci_firmware_group_node:
+ <<: *aci_firmware_group_node_present
+ state: absent
+ register: idempotency_delete_firmware_group_1
+
+ - name: Delete second firmware group (normal_mode)
+ aci_firmware_group_node:
+ <<: *aci_firmware_group_node_2_present
+ state: absent
+ register: nm_delete_firmware_group_node_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_firmware_group_node_1 is changed
+ - cm_delete_firmware_group_node_1.proposed == {}
+ - nm_delete_firmware_group_node_1 is changed
+ - nm_delete_firmware_group_node_1.previous != []
+ - nm_delete_firmware_group_node_1.current == []
+ - idempotency_delete_firmware_group_1 is not changed
+ - idempotency_delete_firmware_group_1.previous == []
+ - nm_delete_firmware_group_node_2 is changed
+ - nm_delete_firmware_group_node_2.previous != []
+ - nm_delete_firmware_group_node_2.current == []
+
+ - name: Delete firmware group - clean up the environment
+ aci_firmware_group:
+ <<: *aci_firmware_group_present
+ state: absent
+
+ - name: Delete firmware policy - clean up the environment
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml
new file mode 100644
index 000000000..ec0bb88ae
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_policy/tasks/main.yml
@@ -0,0 +1,143 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Ensure first firmware policy does not exist
+ aci_firmware_policy: &aci_firmware_policy_absent
+ <<: *aci_info
+ name: anstest_policy
+ version: n9000-15.2(7)
+ ignore_compat: true
+ state: absent
+
+ - name: Ensure second firmware policy does not exist
+ aci_firmware_policy: &aci_firmware_policy_2_absent
+ <<: *aci_info
+ name: anstest_policy_2
+ version: n9000-16.0(1)
+ state: absent
+
+ - name: Create first firmware policy (check_mode)
+ aci_firmware_policy: &aci_firmware_policy_present
+ <<: *aci_firmware_policy_absent
+ state: present
+ check_mode: true
+ register: cm_add_firmware_policy_1
+
+ - name: Create first firmware policy (normal_mode)
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ register: nm_add_firmware_policy_1
+
+ - name: Create first firmware policy again - testing idempotency
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ register: idempotency_add_firmware_policy_1
+
+ - name: Create second firmware policy
+ aci_firmware_policy: &aci_firmware_policy_2_present
+ <<: *aci_firmware_policy_2_absent
+ state: present
+ register: nm_add_firmware_policy_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_firmware_policy_1 is changed
+ - cm_add_firmware_policy_1.previous == []
+ - cm_add_firmware_policy_1.current == []
+ - nm_add_firmware_policy_1 is changed
+ - nm_add_firmware_policy_1.current.0.firmwareFwP.attributes.name == "anstest_policy"
+ - nm_add_firmware_policy_1.current.0.firmwareFwP.attributes.ignoreCompat == "yes"
+ - nm_add_firmware_policy_1.current.0.firmwareFwP.attributes.version == "n9000-15.2(7)"
+ - idempotency_add_firmware_policy_1 is not changed
+ - nm_add_firmware_policy_2 is changed
+ - nm_add_firmware_policy_2.current.0.firmwareFwP.attributes.name == "anstest_policy_2"
+ - nm_add_firmware_policy_2.current.0.firmwareFwP.attributes.ignoreCompat == "no"
+ - nm_add_firmware_policy_2.current.0.firmwareFwP.attributes.version == "n9000-16.0(1)"
+
+ - name: Query all firmware policies
+ aci_firmware_policy:
+ <<: *aci_info
+ state: query
+ register: query_all_firmware_policy
+
+ - name: Query first firmware policy
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ state: query
+ register: query_first_firmware_policy
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_firmware_policy is not changed
+ - query_all_firmware_policy.current | length >= 2
+ - '"class/firmwareFwP.json" in query_all_firmware_policy.url'
+ - query_first_firmware_policy is not changed
+ - query_first_firmware_policy.current.0.firmwareFwP.attributes.name == "anstest_policy"
+ - query_first_firmware_policy.current.0.firmwareFwP.attributes.ignoreCompat == "yes"
+ - query_first_firmware_policy.current.0.firmwareFwP.attributes.version == "n9000-15.2(7)"
+
+ - name: Delete first firmware policy (check_mode)
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ state: absent
+ check_mode: true
+ register: cm_delete_firmware_policy_1
+
+ - name: Delete first firmware policy (normal_mode)
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ state: absent
+ register: nm_delete_firmware_policy_1
+
+ - name: Delete first firmware policy again - testing idempotency
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_present
+ state: absent
+ register: idempotency_delete_firmware_policy_1
+
+ - name: Delete second firmware policy (normal_mode)
+ aci_firmware_policy:
+ <<: *aci_firmware_policy_2_present
+ state: absent
+ register: nm_delete_firmware_policy_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_firmware_policy_1 is changed
+ - cm_delete_firmware_policy_1.proposed == {}
+ - nm_delete_firmware_policy_1 is changed
+ - nm_delete_firmware_policy_1.previous != []
+ - nm_delete_firmware_policy_1.current == []
+ - idempotency_delete_firmware_policy_1 is not changed
+ - idempotency_delete_firmware_policy_1.previous == []
+ - nm_delete_firmware_policy_2 is changed
+ - nm_delete_firmware_policy_2.previous != []
+ - nm_delete_firmware_policy_2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml
index d7b125267..17e0bb67c 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml
@@ -45,6 +45,40 @@
- 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: Query blacklisted interfaces
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ state: query
+ register: enable_and_clear
+
+ - name: set regex
+ set_fact:
+ regexp: '(topology/pod-)(\d)(/paths-)(\d*)(/pathep-\[eth)(.*)(])'
+
+ - name: Save Target DNs
+ set_fact:
+ tdn: "{{ item.fabricRsOosPath.attributes.tDn }}"
+ loop: "{{ enable_and_clear.current }}"
+ register: enabled_tdn
+
+ - name: Enable interfaces that were blacklisted
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ pod_id: "{{ item.ansible_facts.tdn | regex_search(regexp, '\\2') | first }}"
+ node_id: "{{ item.ansible_facts.tdn | regex_search(regexp, '\\4') | first }}"
+ interface: "{{ item.ansible_facts.tdn | regex_search(regexp, '\\6') | first }}"
+ state: absent
+ loop: "{{ enabled_tdn.results }}"
+
+ - name: Ensure Interfaces are absent - Clean up test environment
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: "{{ item.ansible_facts.tdn | regex_search(regexp, '\\4') | first }}"
+ interface: "{{ item.ansible_facts.tdn | regex_search(regexp, '\\6') | first }}"
+ state: absent
+ loop: "{{ enabled_tdn.results }}"
+
- name: Spine - Clean test environment with enabled interface
cisco.aci.aci_interface_blacklist:
<<: *aci_info
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml
index 75253bd40..3e8ebcb82 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml
@@ -42,7 +42,7 @@
role: leaf
port_type: access
interface_type: switch_port
- interface: "1/1/1"
+ interface: "1/1"
state: absent
register: invalid_interface_absent
ignore_errors: true
@@ -68,7 +68,7 @@
policy_group: ans_test_switch_port
node: 501
breakout: "100g-4x"
- interface: "1/1/1"
+ interface: "1/1"
state: present
register: invalid_policy_group_with_breakout
ignore_errors: true
@@ -86,7 +86,7 @@
cisco.aci.aci_interface_config:
<<: *aci_info
node: 5000
- interface: "1/1/1"
+ interface: "1/1"
state: present
register: invalid_node
ignore_errors: true
@@ -141,7 +141,7 @@
- invalid_sub_port is not changed
- invalid_sub_port.msg is match("^Sub Port ID{{':'}} .+? is invalid; it must be in the range of 0 to 16.")
- - name: Ensure Interface 501 with leaf access with policy_group - switch_port absent
+ - name: Ensure Interface 501 with leaf access with policy_group and without sub port - switch_port absent
cisco.aci.aci_interface_config: &interface_501_absent
<<: *aci_info
role: leaf
@@ -149,20 +149,20 @@
interface_type: switch_port
policy_group: ans_test_switch_port
node: 501
- interface: "1/1/1"
+ interface: "1/1"
description: "Interface - 501 added by Ansible"
admin_state: "down"
state: absent
register: interface_501_absent
- - name: Ensure Interface 501 with leaf access with policy_group - switch_port present - check mode
+ - name: Ensure Interface 501 with leaf access with policy_group and without sub port - switch_port present - check mode
cisco.aci.aci_interface_config: &cm_interface_501_present
<<: *interface_501_absent
state: present
check_mode: true
register: cm_interface_501_present
- - name: Ensure Interface 501 with leaf access with policy_group - switch_port present - normal mode
+ - name: Ensure Interface 501 with leaf access with policy_group and without sub port - switch_port present - normal mode
cisco.aci.aci_interface_config: &nm_interface_501_present
<<: *interface_501_absent
state: present
@@ -178,13 +178,13 @@
- nm_interface_501_present.current != []
- nm_interface_501_present.current.0.infraPortConfig.attributes.assocGrp == "uni/infra/funcprof/accportgrp-ans_test_switch_port"
- nm_interface_501_present.current.0.infraPortConfig.attributes.brkoutMap == "none"
- - nm_interface_501_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-501-card-1-port-1-sub-1"
+ - nm_interface_501_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-501-card-1-port-1-sub-0"
- nm_interface_501_present.current.0.infraPortConfig.attributes.node == "501"
- nm_interface_501_present.current.0.infraPortConfig.attributes.role == "leaf"
- nm_interface_501_present.current.0.infraPortConfig.attributes.shutdown == "yes"
- nm_interface_501_present.current.0.infraPortConfig.attributes.card == "1"
- nm_interface_501_present.current.0.infraPortConfig.attributes.port == "1"
- - nm_interface_501_present.current.0.infraPortConfig.attributes.subPort == "1"
+ - nm_interface_501_present.current.0.infraPortConfig.attributes.subPort == "0"
- name: Ensure Interface 502 with leaf access with policy_group - pc_or_vpc absent
cisco.aci.aci_interface_config: &interface_502_absent
@@ -461,7 +461,7 @@
policy_group: ans_test_switch_port
breakout: "100g-4x"
node: 501
- interface: "1/1/1"
+ interface: "1/1"
description: "Interface - 501 added by Ansible"
state: present
register: invalid_breakout_501_present
@@ -475,7 +475,7 @@
interface_type: switch_port
breakout: "100g-4x"
node: 501
- interface: "1/1/1"
+ interface: "1/1"
description: "Interface - 501 added by Ansible"
admin_state: "down"
state: present
@@ -504,14 +504,14 @@
- nm_valid_breakout_501_present.current != []
- nm_valid_breakout_501_present.current.0.infraPortConfig.attributes.brkoutMap == "100g-4x"
- nm_valid_breakout_501_present.current.0.infraPortConfig.attributes.description == "Interface - 501 added by Ansible"
- - nm_valid_breakout_501_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-501-card-1-port-1-sub-1"
+ - nm_valid_breakout_501_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-501-card-1-port-1-sub-0"
- nm_valid_breakout_501_present.current.0.infraPortConfig.attributes.role == "leaf"
- nm_valid_breakout_501_present.current.0.infraPortConfig.attributes.shutdown == "yes"
- idm_breakout_501_present is not changed
- idm_breakout_501_present.current != []
- idm_breakout_501_present.current.0.infraPortConfig.attributes.brkoutMap == "100g-4x"
- idm_breakout_501_present.current.0.infraPortConfig.attributes.description == "Interface - 501 added by Ansible"
- - idm_breakout_501_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-501-card-1-port-1-sub-1"
+ - idm_breakout_501_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-501-card-1-port-1-sub-0"
- idm_breakout_501_present.current.0.infraPortConfig.attributes.role == "leaf"
- idm_breakout_501_present.current.0.infraPortConfig.attributes.shutdown == "yes"
# Breakup part ends
@@ -527,7 +527,7 @@
assert:
that:
- query_all_access_interfaces is not changed
- - query_all_access_interfaces.current|length >= 6
+ - query_all_access_interfaces.current|length >= 5
- name: Query all fabric interfaces
cisco.aci.aci_interface_config:
@@ -678,3 +678,19 @@
that:
- query_interface_509 is not changed
- query_interface_509.current == []
+
+ - name: Ensure Interfaces 50* are absent - Clean up test environment
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: "{{ item.node }}"
+ interface: "{{ item.interface }}"
+ state: absent
+ with_items:
+ - { node: "501", interface: "1/1/1" }
+ - { node: "502", interface: "2/2/2" }
+ - { node: "503", interface: "1/1/1" }
+ - { node: "505", interface: "5/5/5" }
+ - { node: "506", interface: "6/6/6" }
+ - { node: "507", interface: "7/7/7" }
+ - { node: "508", interface: "8/8/8" }
+ - { node: "509", interface: "9/9/9" }
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml
new file mode 100644
index 000000000..5e039380e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_fc/tasks/main.yml
@@ -0,0 +1,160 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Ensure first fc interface policy does not exist
+ aci_interface_policy_fc: &aci_interface_policy_fc_absent
+ <<: *aci_info
+ name: anstest_policy
+ description: test for fc interface policy
+ port_mode: np
+ auto_max_speed: 16G
+ fill_pattern: arbff
+ buffer_credits: 32
+ speed: 8G
+ trunk_mode: trunk-on
+ state: absent
+
+ - name: Ensure second fc interface policy does not exist
+ aci_interface_policy_fc: &aci_interface_policy_fc_2_absent
+ <<: *aci_info
+ name: anstest_policy_2
+ state: absent
+
+ - name: Create first fc interface policy (check_mode)
+ aci_interface_policy_fc: &aci_interface_policy_fc_present
+ <<: *aci_interface_policy_fc_absent
+ state: present
+ check_mode: true
+ register: cm_add_interface_policy_fc_1
+
+ - name: Create first fc interface policy (normal_mode)
+ aci_interface_policy_fc:
+ <<: *aci_interface_policy_fc_present
+ register: nm_add_interface_policy_fc_1
+
+ - name: Create first fc interface policy again - testing idempotency
+ aci_interface_policy_fc:
+ <<: *aci_interface_policy_fc_present
+ register: idempotency_add_interface_policy_fc_1
+
+ - name: Create second fc interface policy
+ aci_interface_policy_fc: &aci_interface_policy_fc_2_present
+ <<: *aci_interface_policy_fc_2_absent
+ state: present
+ register: nm_add_interface_policy_fc_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_interface_policy_fc_1 is changed
+ - cm_add_interface_policy_fc_1.previous == []
+ - cm_add_interface_policy_fc_1.current == []
+ - nm_add_interface_policy_fc_1 is changed
+ - nm_add_interface_policy_fc_1.current.0.fcIfPol.attributes.name == "anstest_policy"
+ - nm_add_interface_policy_fc_1.current.0.fcIfPol.attributes.portMode == "np"
+ - nm_add_interface_policy_fc_1.current.0.fcIfPol.attributes.automaxspeed == "16G"
+ - nm_add_interface_policy_fc_1.current.0.fcIfPol.attributes.fillPattern == "ARBFF"
+ - nm_add_interface_policy_fc_1.current.0.fcIfPol.attributes.rxBBCredit == "32"
+ - nm_add_interface_policy_fc_1.current.0.fcIfPol.attributes.speed == "8G"
+ - nm_add_interface_policy_fc_1.current.0.fcIfPol.attributes.trunkMode == "trunk-on"
+ - idempotency_add_interface_policy_fc_1 is not changed
+ - nm_add_interface_policy_fc_2 is changed
+ - nm_add_interface_policy_fc_2.current.0.fcIfPol.attributes.name == "anstest_policy_2"
+ - nm_add_interface_policy_fc_2.current.0.fcIfPol.attributes.portMode == "f"
+ - nm_add_interface_policy_fc_2.current.0.fcIfPol.attributes.automaxspeed == "32G"
+ - nm_add_interface_policy_fc_2.current.0.fcIfPol.attributes.fillPattern == "IDLE"
+ - nm_add_interface_policy_fc_2.current.0.fcIfPol.attributes.rxBBCredit == "64"
+ - nm_add_interface_policy_fc_2.current.0.fcIfPol.attributes.speed == "auto"
+ - nm_add_interface_policy_fc_2.current.0.fcIfPol.attributes.trunkMode == "trunk-off"
+ - idempotency_add_interface_policy_fc_1 is not changed
+
+ - name: Query all fc interface policies
+ aci_interface_policy_fc:
+ <<: *aci_info
+ state: query
+ register: query_all_interface_policy_fc
+
+ - name: Query first fc interface policy
+ aci_interface_policy_fc:
+ <<: *aci_interface_policy_fc_present
+ state: query
+ register: query_first_interface_policy_fc
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_interface_policy_fc is not changed
+ - query_all_interface_policy_fc.current | length >= 2
+ - '"class/fcIfPol.json" in query_all_interface_policy_fc.url'
+ - query_first_interface_policy_fc is not changed
+ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.name == "anstest_policy"
+ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.portMode == "np"
+ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.automaxspeed == "16G"
+ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.fillPattern == "ARBFF"
+ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.rxBBCredit == "32"
+ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.speed == "8G"
+ - query_first_interface_policy_fc.current.0.fcIfPol.attributes.trunkMode == "trunk-on"
+
+ - name: Delete first fc interface policy (check_mode)
+ aci_interface_policy_fc:
+ <<: *aci_interface_policy_fc_present
+ state: absent
+ check_mode: true
+ register: cm_delete_interface_policy_fc_1
+
+ - name: Delete first fc interface policy (normal_mode)
+ aci_interface_policy_fc:
+ <<: *aci_interface_policy_fc_present
+ state: absent
+ register: nm_delete_interface_policy_fc_1
+
+ - name: Delete first fc interface policy again - testing idempotency
+ aci_interface_policy_fc:
+ <<: *aci_interface_policy_fc_present
+ state: absent
+ register: idempotency_delete_interface_policy_fc_1
+
+ - name: Delete second fc interface policy (normal_mode)
+ aci_interface_policy_fc:
+ <<: *aci_interface_policy_fc_2_present
+ state: absent
+ register: nm_delete_interface_policy_fc_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_interface_policy_fc_1 is changed
+ - cm_delete_interface_policy_fc_1.proposed == {}
+ - nm_delete_interface_policy_fc_1 is changed
+ - nm_delete_interface_policy_fc_1.previous != []
+ - nm_delete_interface_policy_fc_1.current == []
+ - idempotency_delete_interface_policy_fc_1 is not changed
+ - idempotency_delete_interface_policy_fc_1.previous == []
+ - nm_delete_interface_policy_fc_2 is changed
+ - nm_delete_interface_policy_fc_2.previous != []
+ - nm_delete_interface_policy_fc_2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml
new file mode 100644
index 000000000..f52b74fdb
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_l2/tasks/main.yml
@@ -0,0 +1,147 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Ensure first l2 interface policy does not exist
+ aci_interface_policy_l2: &aci_interface_policy_l2_absent
+ <<: *aci_info
+ name: anstest_policy
+ description: test for l2 interface policy
+ vlan_scope: portlocal
+ qinq: core
+ vepa: true
+ state: absent
+
+ - name: Ensure second l2 interface policy does not exist
+ aci_interface_policy_l2: &aci_interface_policy_l2_2_absent
+ <<: *aci_info
+ name: anstest_policy_2
+ state: absent
+
+ - name: Create first l2 interface policy (check_mode)
+ aci_interface_policy_l2: &aci_interface_policy_l2_present
+ <<: *aci_interface_policy_l2_absent
+ state: present
+ check_mode: true
+ register: cm_add_interface_policy_l2_1
+
+ - name: Create first l2 interface policy (normal_mode)
+ aci_interface_policy_l2:
+ <<: *aci_interface_policy_l2_present
+ register: nm_add_interface_policy_l2_1
+
+ - name: Create first l2 interface policy again - testing idempotency
+ aci_interface_policy_l2:
+ <<: *aci_interface_policy_l2_present
+ register: idempotency_add_interface_policy_l2_1
+
+ - name: Create second l2 interface policy
+ aci_interface_policy_l2: &aci_interface_policy_l2_2_present
+ <<: *aci_interface_policy_l2_2_absent
+ state: present
+ register: nm_add_interface_policy_l2_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_interface_policy_l2_1 is changed
+ - cm_add_interface_policy_l2_1.previous == []
+ - cm_add_interface_policy_l2_1.current == []
+ - nm_add_interface_policy_l2_1 is changed
+ - nm_add_interface_policy_l2_1.current.0.l2IfPol.attributes.name == "anstest_policy"
+ - nm_add_interface_policy_l2_1.current.0.l2IfPol.attributes.vlanScope == "portlocal"
+ - nm_add_interface_policy_l2_1.current.0.l2IfPol.attributes.qinq == "corePort"
+ - nm_add_interface_policy_l2_1.current.0.l2IfPol.attributes.vepa == "enabled"
+ - idempotency_add_interface_policy_l2_1 is not changed
+ - nm_add_interface_policy_l2_2 is changed
+ - nm_add_interface_policy_l2_2.current.0.l2IfPol.attributes.name == "anstest_policy_2"
+ - nm_add_interface_policy_l2_2.current.0.l2IfPol.attributes.vlanScope == "global"
+ - nm_add_interface_policy_l2_2.current.0.l2IfPol.attributes.qinq == "disabled"
+ - nm_add_interface_policy_l2_2.current.0.l2IfPol.attributes.vepa == "disabled"
+
+ - name: Query all l2 interface policies
+ aci_interface_policy_l2:
+ <<: *aci_info
+ state: query
+ register: query_all_interface_policy_l2
+
+ - name: Query first l2 interface policy
+ aci_interface_policy_l2:
+ <<: *aci_interface_policy_l2_present
+ state: query
+ register: query_first_interface_policy_l2
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_interface_policy_l2 is not changed
+ - query_all_interface_policy_l2.current | length >= 2
+ - '"class/l2IfPol.json" in query_all_interface_policy_l2.url'
+ - query_first_interface_policy_l2 is not changed
+ - query_first_interface_policy_l2.current.0.l2IfPol.attributes.name == "anstest_policy"
+ - query_first_interface_policy_l2.current.0.l2IfPol.attributes.vlanScope == "portlocal"
+ - query_first_interface_policy_l2.current.0.l2IfPol.attributes.qinq == "corePort"
+ - query_first_interface_policy_l2.current.0.l2IfPol.attributes.vepa == "enabled"
+
+ - name: Delete first l2 interface policy (check_mode)
+ aci_interface_policy_l2:
+ <<: *aci_interface_policy_l2_present
+ state: absent
+ check_mode: true
+ register: cm_delete_interface_policy_l2_1
+
+ - name: Delete first l2 interface policy (normal_mode)
+ aci_interface_policy_l2:
+ <<: *aci_interface_policy_l2_present
+ state: absent
+ register: nm_delete_interface_policy_l2_1
+
+ - name: Delete first l2 interface policy again - testing idempotency
+ aci_interface_policy_l2:
+ <<: *aci_interface_policy_l2_present
+ state: absent
+ register: idempotency_delete_interface_policy_l2_1
+
+ - name: Delete second l2 interface policy (normal_mode)
+ aci_interface_policy_l2:
+ <<: *aci_interface_policy_l2_2_present
+ state: absent
+ register: nm_delete_interface_policy_l2_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_interface_policy_l2_1 is changed
+ - cm_delete_interface_policy_l2_1.proposed == {}
+ - nm_delete_interface_policy_l2_1 is changed
+ - nm_delete_interface_policy_l2_1.previous != []
+ - nm_delete_interface_policy_l2_1.current == []
+ - idempotency_delete_interface_policy_l2_1 is not changed
+ - idempotency_delete_interface_policy_l2_1.previous == []
+ - nm_delete_interface_policy_l2_2 is changed
+ - nm_delete_interface_policy_l2_2.previous != []
+ - nm_delete_interface_policy_l2_2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml
new file mode 100644
index 000000000..5a758bb3d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_fc_policy_group/tasks/main.yml
@@ -0,0 +1,231 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Anvitha Jain <anvjain@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+
+ # CLEAN ENVIRONMENT
+ - name: Making sure FC port policy group doesn't exist at beginning of test
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group: &fc_absent
+ <<: *aci_info
+ lag_type: port
+ policy_group: fc_port_test
+ state: absent
+
+ - name: Making sure FC PC policy group doesn't exist at beginning of test
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group: &fc_pc_absent
+ <<: *aci_info
+ lag_type: port_channel
+ policy_group: fc_pc_test
+ state: absent
+
+ # ADD Leaf Access FC Port Policy Group
+ - name: Adding a interface policy Leaf Access FC Port policy group - check mode works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group: &fc_present
+ <<: *aci_info
+ policy_group: fc_port_test
+ lag_type: port
+ fibre_channel_interface_policy: fibre_channel_interface_policy_test
+ attached_entity_profile: test_aep
+ state: present
+ check_mode: yes
+ register: intf_policy_leaf_access_fc_port_polgrp_check_mode_present
+
+ - name: Adding a interface policy Leaf Access FC Port policy group - creation works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_present
+ register: intf_policy_leaf_access_fc_port_polgrp_present
+
+ - name: Adding a interface policy Leaf Access FC Port policy group - idempotency works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_present
+ register: intf_policy_leaf_access_fc_port_polgrp_idempotent
+
+ # UPDATE Leaf Access FC Port Policy Group
+ - name: Adding a interface policy Leaf Access FC Port policy group description - update works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_present
+ description: policygroup description
+ register: intf_policy_leaf_access_fc_port_polgrp_update
+
+ - name: Verify present assertions for FC Port Policy Group
+ assert:
+ that:
+ - intf_policy_leaf_access_fc_port_polgrp_check_mode_present is changed
+ - intf_policy_leaf_access_fc_port_polgrp_present is changed
+ - intf_policy_leaf_access_fc_port_polgrp_present.previous == []
+ - intf_policy_leaf_access_fc_port_polgrp_present.current[0].infraFcAccPortGrp.attributes.name == 'fc_port_test'
+ - intf_policy_leaf_access_fc_port_polgrp_present.current[0].infraFcAccPortGrp.children.0.infraRsFcAttEntP.attributes.tDn == 'uni/infra/attentp-test_aep'
+ - intf_policy_leaf_access_fc_port_polgrp_present.current[0].infraFcAccPortGrp.children.1.infraRsFcL2IfPol.attributes.tnFcIfPolName == 'fibre_channel_interface_policy_test'
+ - intf_policy_leaf_access_fc_port_polgrp_present.current[0].infraFcAccPortGrp.attributes.annotation == 'orchestrator:ansible'
+ - intf_policy_leaf_access_fc_port_polgrp_idempotent is not changed
+ - intf_policy_leaf_access_fc_port_polgrp_idempotent.sent == {}
+ - intf_policy_leaf_access_fc_port_polgrp_update is changed
+ - intf_policy_leaf_access_fc_port_polgrp_update.current[0].infraFcAccPortGrp.attributes.descr == 'policygroup description'
+
+ # ADD Leaf Access FC PC Policy Group
+ - name: Adding a interface policy Leaf Access FC PC policy group - check mode works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group: &fc_pc_present
+ <<: *aci_info
+ policy_group: fc_pc_test
+ lag_type: port_channel
+ fibre_channel_interface_policy: fibre_channel_interface_policy_test
+ port_channel_policy: port_channel_policy_test
+ attached_entity_profile: policy_group_aep
+ state: present
+ check_mode: yes
+ register: intf_policy_leaf_access_fc_pc_polgrp_check_mode_present
+
+ - name: Adding a interface policy Leaf Access FC PC policy group - creation works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_pc_present
+ register: intf_policy_leaf_access_fc_pc_polgrp_present
+
+ - name: Adding a interface policy Leaf Access FC PC policy group - idempotency works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_pc_present
+ register: intf_policy_leaf_access_fc_pc_polgrp_idempotent
+
+ # UPDATE Leaf Access FC PC Policy Group
+ - name: Adding a interface policy Leaf Access FC PC policy group description - update works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_pc_present
+ description: policygroup description
+ register: intf_policy_leaf_access_fc_pc_polgrp_update
+
+ - name: Verify present assertions for FC PC Policy Group
+ assert:
+ that:
+ - intf_policy_leaf_access_fc_pc_polgrp_check_mode_present is changed
+ - intf_policy_leaf_access_fc_pc_polgrp_present is changed
+ - intf_policy_leaf_access_fc_pc_polgrp_present.previous == []
+ - intf_policy_leaf_access_fc_pc_polgrp_present.current[0].infraFcAccBndlGrp.attributes.name == 'fc_pc_test'
+ - intf_policy_leaf_access_fc_pc_polgrp_present.current[0].infraFcAccBndlGrp.children.0.infraRsFcLagPol.attributes.tnLacpLagPolName == 'port_channel_policy_test'
+ - intf_policy_leaf_access_fc_pc_polgrp_present.current[0].infraFcAccBndlGrp.children.1.infraRsFcAttEntP.attributes.tDn == 'uni/infra/attentp-policy_group_aep'
+ - intf_policy_leaf_access_fc_pc_polgrp_present.current[0].infraFcAccBndlGrp.children.2.infraRsFcL2IfPol.attributes.tnFcIfPolName == 'fibre_channel_interface_policy_test'
+ - intf_policy_leaf_access_fc_pc_polgrp_present.current[0].infraFcAccBndlGrp.attributes.annotation == 'orchestrator:ansible'
+ - intf_policy_leaf_access_fc_pc_polgrp_idempotent is not changed
+ - intf_policy_leaf_access_fc_pc_polgrp_idempotent.sent == {}
+ - intf_policy_leaf_access_fc_pc_polgrp_update is changed
+ - intf_policy_leaf_access_fc_pc_polgrp_update.current[0].infraFcAccBndlGrp.attributes.descr == 'policygroup description'
+
+
+ # QUERY Leaf Access FC Port Policy Group
+ - name: Query all interface policy Leaf Access FC Port policy groups
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *aci_info
+ lag_type: port
+ state: query
+ register: query_all_leaf_access_fc_port_policy_groups
+
+ - name: Query interface policy Leaf Access FC Port policy group
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *aci_info
+ policy_group: fc_port_test
+ lag_type: port
+ state: query
+ register: query_leaf_access_fc_port_policy_group
+
+ - name: Verify query assertions for Leaf Access FC Port Policy Group
+ assert:
+ that:
+ - query_leaf_access_fc_port_policy_group is not changed
+ - query_leaf_access_fc_port_policy_group.current[0] | length >= 1
+ - query_all_leaf_access_fc_port_policy_groups is not changed
+
+ # QUERY Leaf Access FC PC Policy Group
+ - name: Query all interface policy Leaf Access FC PC policy groups
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *aci_info
+ lag_type: port_channel
+ state: query
+ register: query_all_leaf_access_fc_pc_policy_groups
+
+ - name: Query interface policy Leaf Access FC PC policy group
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *aci_info
+ policy_group: fc_pc_test
+ lag_type: port_channel
+ state: query
+ register: query_leaf_access_fc_pc_policy_group
+
+ - name: Verify query assertions for Leaf Access FC PC Policy Group
+ assert:
+ that:
+ - query_leaf_access_fc_pc_policy_group is not changed
+ - query_leaf_access_fc_pc_policy_group.current[0] | length >= 1
+ - query_all_leaf_access_fc_pc_policy_groups is not changed
+
+ # DELETE Leaf Access FC Port Policy Group
+ - name: Remove interface policy Leaf Access FC Port policy group - check mode
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_absent
+ check_mode: yes
+ register: intf_policy_leaf_access_fc_port_polgrp_check_mode_absent
+
+ - name: Remove interface policy Leaf Access FC Port policy group - delete works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_absent
+ register: intf_policy_leaf_access_fc_port_polgrp_absent
+
+ - name: Remove interface policy Leaf Access FC Port policy group - idempotency works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_absent
+ register: intf_policy_leaf_access_fc_port_polgrp_absent_idempotent
+
+ - name: Verify absent assertions for FC Port Policy Group
+ assert:
+ that:
+ - intf_policy_leaf_access_fc_port_polgrp_check_mode_absent is changed
+ - intf_policy_leaf_access_fc_port_polgrp_check_mode_absent.previous != []
+ - intf_policy_leaf_access_fc_port_polgrp_absent is changed
+ - intf_policy_leaf_access_fc_port_polgrp_absent_idempotent is not changed
+ - intf_policy_leaf_access_fc_port_polgrp_absent_idempotent.previous == []
+
+ # DELETE Leaf Access FC PC Policy Group
+ - name: Remove interface policy Leaf Access FC PC policy group - check mode
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_pc_absent
+ check_mode: yes
+ register: intf_policy_leaf_access_fc_pc_polgrp_check_mode_absent
+
+ - name: Remove interface policy Leaf Access FC PC policy group - delete works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_pc_absent
+ register: intf_policy_leaf_access_fc_pc_polgrp_absent
+
+ - name: Remove interface policy Leaf Access FC PC policy group - idempotency works
+ cisco.aci.aci_interface_policy_leaf_fc_policy_group:
+ <<: *fc_pc_absent
+ register: intf_policy_leaf_access_fc_pc_polgrp_absent_idempotent
+
+ - name: Verify absent assertions for FC PC policy group
+ assert:
+ that:
+ - intf_policy_leaf_access_fc_pc_polgrp_check_mode_absent is changed
+ - intf_policy_leaf_access_fc_pc_polgrp_check_mode_absent.previous != []
+ - intf_policy_leaf_access_fc_pc_polgrp_absent is changed
+ - intf_policy_leaf_access_fc_pc_polgrp_absent_idempotent is not changed
+ - intf_policy_leaf_access_fc_pc_polgrp_absent_idempotent.previous == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml
index f94ba4e48..3f6e25505 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml
@@ -1,4 +1,5 @@
# Test code for the ACI modules
+# Copyright: (c) 2023, Anvitha Jain <anvjain@cisco.com>
# Copyright: (c) 2017, Bruno Calogero <brunocalogero@hotmail.com>
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -8,6 +9,25 @@
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
+# GET Credentials from the inventory
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: "{{ aci_validate_certs | default(false) }}"
+ use_ssl: "{{ aci_use_ssl | default(true) }}"
+ use_proxy: "{{ aci_use_proxy | default(true) }}"
+ output_level: debug
+
+- name: Query system information
+ cisco.aci.aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
- name: Verify Cloud and Non-Cloud Sites in use.
include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
@@ -16,55 +36,30 @@
block: # block specifies execution of tasks within, based on conditions
- name: Making sure interface_policy_leaf_policy_group doesn't exist at beginning of test (PC)
cisco.aci.aci_interface_policy_leaf_policy_group: &aci_interface_policy_leaf_policy_group_link_absent
- 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
policy_group: policygroupname_link
lag_type: link
state: absent
- name: Making sure interface_policy_leaf_policy_group doesn't exist at beginning of test (VPC)
cisco.aci.aci_interface_policy_leaf_policy_group: &aci_interface_policy_leaf_policy_group_node_absent
- 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
policy_group: policygroupname_node
lag_type: node
state: absent
- name: Making sure interface_policy_leaf_policy_group doesn't exist at beginning of test (Leaf Access Port)
cisco.aci.aci_interface_policy_leaf_policy_group: &aci_interface_policy_leaf_policy_group_leaf_absent
- 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
policy_group: policygroupname_leaf
lag_type: leaf
state: absent
-
# ==== TESTING Port Channel (PC), lag_type: link ====
- name: Adding a interface policy leaf policy group (PC) - check mode works
cisco.aci.aci_interface_policy_leaf_policy_group: &aci_interface_policy_leaf_policy_group_link_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
policy_group: policygroupname_link
lag_type: link
link_level_policy: linklevelpolicy
@@ -90,7 +85,7 @@
register: intf_policy_leaf_polgrp_update
# TODO: also test for errors
- - name: present assertions
+ - name: present assertions for interface policy leaf policy group (PC)
assert:
that:
- intf_policy_leaf_polgrp_check_mode_present is changed
@@ -108,19 +103,13 @@
- name: Query interface policy leaf policy group (PC)
cisco.aci.aci_interface_policy_leaf_policy_group:
- 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
policy_group: policygroupname_link
lag_type: link
state: query
register: binding_query
- - name: present assertions
+ - name: Query assertions for interface policy leaf policy group (PC)
assert:
that:
- binding_query is not changed
@@ -145,20 +134,14 @@
- name: Remove interface policy leaf policy group (PC) - check mode
cisco.aci.aci_interface_policy_leaf_policy_group:
- 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
policy_group: policygroupname_link
#lag_type: link
state: absent
ignore_errors: true
register: intf_policy_leaf_polgrp_absent_missing_param
- - name: absent assertions
+ - name: absent assertions for interface policy leaf policy group (PC)
assert:
that:
- intf_policy_leaf_polgrp_check_mode_absent is changed
@@ -181,13 +164,7 @@
- name: Adding a interface policy leaf policy group (VPC) - check mode works
cisco.aci.aci_interface_policy_leaf_policy_group: &aci_interface_policy_leaf_policy_group_node_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
policy_group: policygroupname_node
lag_type: node
link_level_policy: linklevelpolicy
@@ -213,7 +190,7 @@
register: intf_policy_leaf_polgrp_update
# TODO: also test for errors
- - name: present assertions
+ - name: present assertions for interface policy leaf policy group (VPC)
assert:
that:
- intf_policy_leaf_polgrp_check_mode_present is changed
@@ -231,19 +208,13 @@
- name: Query interface policy leaf policy group (VPC)
cisco.aci.aci_interface_policy_leaf_policy_group:
- 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
policy_group: policygroupname_node
lag_type: node
state: query
register: binding_query
- - name: present assertions
+ - name: Query assertions for interface policy leaf policy group (VPC)
assert:
that:
- binding_query is not changed
@@ -258,18 +229,12 @@
- name: Query interface policy leaf policy group (VPC)
cisco.aci.aci_interface_policy_leaf_policy_group:
- 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
lag_type: node
state: query
register: binding_query_node_all
- - name: present assertions
+ - name: Query assertions for interface policy leaf policy group (VPC)
assert:
that:
- binding_query_node_all is not changed
@@ -293,22 +258,15 @@
<<: *aci_interface_policy_leaf_policy_group_node_absent
register: intf_policy_leaf_polgrp_absent_idempotent
- - name: Remove interface policy leaf policy group (VPC) - check mode
+ - name: Remove interface policy leaf policy group (VPC) - without lag_type
cisco.aci.aci_interface_policy_leaf_policy_group:
- 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
policy_group: policygroupname_node
- #lag_type: node
state: absent
ignore_errors: true
register: intf_policy_leaf_polgrp_absent_missing_param
- - name: absent assertions
+ - name: absent assertions for interface policy leaf policy group (VPC)
assert:
that:
- intf_policy_leaf_polgrp_check_mode_absent is changed
@@ -320,6 +278,18 @@
- intf_policy_leaf_polgrp_absent_missing_param is failed
- 'intf_policy_leaf_polgrp_absent_missing_param.msg == "missing required arguments: lag_type"'
+ - name: Adding a interface policy leaf policy group (VPC) - port_channel_policy not supported error
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_present
+ port_authentication: "default"
+ ignore_errors: true
+ register: intf_policy_leaf_polgrp_pa_policy_error
+
+ - name: VPC error assertions (adding invalid parameters)
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_pa_policy_error.msg == 'port_authentication is not a valid parameter for link/node (Port Channel, Virtual Port Channel), if used assign null to it (port_authentication{{":"}} null).'
+
# ==== END TESTING Virtual Port Channel (VPC), lag_type: node ====
@@ -331,17 +301,12 @@
- name: Adding a interface policy leaf policy group (Leaf Access Port) - check mode works
cisco.aci.aci_interface_policy_leaf_policy_group: &aci_interface_policy_leaf_policy_group_leaf_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
policy_group: policygroupname_leaf
lag_type: leaf
link_level_policy: linklevelpolicy
fibre_channel_interface_policy: fiberchannelpolicy
+ aep: test_aep
state: present
check_mode: true
register: intf_policy_leaf_polgrp_check_mode_present
@@ -377,7 +342,7 @@
register: intf_policy_leaf_polgrp_pc_policy_error
# TODO: also test for errors
- - name: present assertions
+ - name: present assertions for interface policy leaf policy group (Leaf Access Port)
assert:
that:
- intf_policy_leaf_polgrp_check_mode_present is changed
@@ -386,6 +351,7 @@
- intf_policy_leaf_polgrp_present.sent.infraAccPortGrp.attributes.name == 'policygroupname_leaf'
- intf_policy_leaf_polgrp_present.sent.infraAccPortGrp.children.0.infraRsFcIfPol.attributes.tnFcIfPolName == 'fiberchannelpolicy'
- intf_policy_leaf_polgrp_present.sent.infraAccPortGrp.children.1.infraRsHIfPol.attributes.tnFabricHIfPolName == 'linklevelpolicy'
+ - intf_policy_leaf_polgrp_present.sent.infraAccPortGrp.children.2.infraRsAttEntP.attributes.tDn == "uni/infra/attentp-test_aep"
- intf_policy_leaf_polgrp_idempotent is not changed
- intf_policy_leaf_polgrp_idempotent.sent == {}
- intf_policy_leaf_polgrp_update is changed
@@ -395,24 +361,19 @@
- name: Query interface policy leaf policy group (Leaf Access Port)
cisco.aci.aci_interface_policy_leaf_policy_group:
- 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
policy_group: policygroupname_leaf
lag_type: leaf
state: query
register: binding_query
- - name: present assertions
+ - name: Query assertions interface policy leaf policy group (Leaf Access Port)
assert:
that:
- binding_query is not changed
- binding_query.current | length >= 1
- '"/api/mo/uni/infra/funcprof/accportgrp-policygroupname_leaf.json" in binding_query.url'
+ - binding_query.current.0.infraAccPortGrp.children.14.infraRsAttEntP.attributes.tDn == "uni/infra/attentp-test_aep"
- name: Remove interface policy leaf policy group (Leaf Access Port) - check mode
cisco.aci.aci_interface_policy_leaf_policy_group:
@@ -430,22 +391,15 @@
<<: *aci_interface_policy_leaf_policy_group_leaf_absent
register: intf_policy_leaf_polgrp_absent_idempotent
- - name: Remove interface policy leaf policy group (Leaf Access Port) - check mode
+ - name: Remove interface policy leaf policy group (Leaf Access Port) - without lag_type
cisco.aci.aci_interface_policy_leaf_policy_group:
- 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
policy_group: policygroupname_leaf
- #lag_type: leaf
state: absent
ignore_errors: true
register: intf_policy_leaf_polgrp_absent_missing_param
- - name: absent assertions
+ - name: absent assertions for interface policy leaf policy group (Leaf Access Port)
assert:
that:
- intf_policy_leaf_polgrp_check_mode_absent is changed
@@ -458,3 +412,129 @@
- 'intf_policy_leaf_polgrp_absent_missing_param.msg == "missing required arguments: lag_type"'
# ==== END TESTING Virtual Port Channel (VPC), lag_type: leaf ====
+
+
+ # ==== START TESTING PortCHannel (PC - lag_type: link), Virtual Port Channel (VPC - node: leaf) and Leaf Interface (lag_type: leaf) ====
+ # ==== For parameters avaiable only for APIC versions > 5 ====
+
+ - name: Execute tasks only for the APIC version version > 5
+ when: version.current.0.topSystem.attributes.version is version('5', '>')
+ block:
+
+ # ==== TESTING Port Channel (PC) ====
+ - name: Adding a interface policy leaf policy group (PC) - APIC version > 5
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_present
+ sync_e_interface_policy: synceinterfacepolicy
+ state: present
+ register: intf_policy_leaf_policy_group_link_present_2
+
+ - name: present assertions (PC) for APIC version > 5
+ assert:
+ that:
+ - intf_policy_leaf_policy_group_link_present_2 is changed
+ - intf_policy_leaf_policy_group_link_present_2.previous != []
+ - intf_policy_leaf_policy_group_link_present_2.current[0].infraAccBndlGrp.attributes.name == 'policygroupname_link'
+ - intf_policy_leaf_policy_group_link_present_2.sent.infraAccBndlGrp.children.0.infraRsSynceEthIfPolBndlGrp.attributes.tnSynceEthIfPolName == 'synceinterfacepolicy'
+
+ # ==== TESTING Leaf Interface ====
+ - name: Adding a interface policy leaf policy group (Leaf Access Port) - APIC version > 5
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ sync_e_interface_policy: synceinterfacepolicy
+ state: present
+ register: intf_policy_leaf_polgrp_present_2
+
+ - name: present assertions (Leaf Access Port) for APIC version > 5
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_present_2 is changed
+ - intf_policy_leaf_polgrp_present_2.previous == []
+ - intf_policy_leaf_polgrp_present_2.sent.infraAccPortGrp.attributes.name == 'policygroupname_leaf'
+ - intf_policy_leaf_polgrp_present_2.sent.infraAccPortGrp.children.0.infraRsFcIfPol.attributes.tnFcIfPolName == 'fiberchannelpolicy'
+ - intf_policy_leaf_polgrp_present_2.sent.infraAccPortGrp.children.1.infraRsHIfPol.attributes.tnFabricHIfPolName == 'linklevelpolicy'
+ - intf_policy_leaf_polgrp_present_2.sent.infraAccPortGrp.children.2.infraRsAttEntP.attributes.tDn == 'uni/infra/attentp-test_aep'
+ - intf_policy_leaf_polgrp_present_2.sent.infraAccPortGrp.children.3.infraRsSynceEthIfPol.attributes.tnSynceEthIfPolName == 'synceinterfacepolicy'
+
+ # ==== END TESTING for parameters avaiable only for APIC versions > 5 ====
+
+
+ # ==== START TESTING PortCHannel (PC - lag_type: link), Virtual Port Channel (VPC - node: leaf) and Leaf Interface (lag_type: leaf) ====
+ # ==== For parameters avaiable only for APIC versions >= 6 ====
+
+ - name: Execute tasks only for the APIC version version >= 6
+ when: version.current.0.topSystem.attributes.version is version('6', '>=')
+ block:
+ # ==== TESTING Virtual Port Channel (VPC) ====
+ - name: Adding a interface policy leaf policy group (VPC) - APIC version > 6
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_node_present
+ sync_e_interface_policy: synceinterfacepolicy
+ state: present
+ register: intf_policy_leaf_policy_group_node_present_2
+
+ - name: present assertions (VPC) for APIC version > 6
+ assert:
+ that:
+ - intf_policy_leaf_policy_group_node_present_2 is changed
+ - intf_policy_leaf_policy_group_node_present_2.previous == []
+ - intf_policy_leaf_policy_group_node_present_2.current[0].infraAccBndlGrp.attributes.name == 'policygroupname_node'
+ - intf_policy_leaf_policy_group_node_present_2.sent.infraAccBndlGrp.children.0.infraRsFcIfPol.attributes.tnFcIfPolName == 'fiberchannelpolicy'
+ - intf_policy_leaf_policy_group_node_present_2.sent.infraAccBndlGrp.children.1.infraRsHIfPol.attributes.tnFabricHIfPolName == 'linklevelpolicy'
+ - intf_policy_leaf_policy_group_node_present_2.sent.infraAccBndlGrp.children.2.infraRsSynceEthIfPolBndlGrp.attributes.tnSynceEthIfPolName == 'synceinterfacepolicy'
+
+ - name: Execute tasks only for the APIC version version >= 6.0.2
+ when: version.current.0.topSystem.attributes.version is version('6.0(2h)', '>=')
+ block:
+ # ==== TESTING Leaf Interface ====
+ - name: Adding a interface policy leaf policy group (Leaf Access Port) - APIC version >= 6.0.2
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ transceiver_policy:
+ name: transceiverpolicy
+ type: zr
+ state: present
+ register: intf_policy_leaf_polgrp_present_3
+
+ - name: present assertions (Leaf Access Port) for APIC version >= 6.0.2
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_present_3 is changed
+ - intf_policy_leaf_polgrp_present_3.previous != []
+ - intf_policy_leaf_polgrp_present_3.current[0].infraAccPortGrp.attributes.name == 'policygroupname_leaf'
+ - intf_policy_leaf_polgrp_present_3.sent.infraAccPortGrp.children.0.infraRsOpticsIfPol.attributes.tDn == 'uni/infra/zr-transceiverpolicy'
+
+ - name: Adding all the policies for leaf policy group (Leaf Access Port)
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ cdp_policy: cdppolicy
+ mcp_policy: mcppolicy
+ lldp_policy: lldppolicy
+ stp_interface_policy: stppolicy
+ egress_data_plane_policing_policy: egressdataplanepolicingpolicy
+ ingress_data_plane_policing_policy: ingressdataplanepolicingpolicy
+ priority_flow_control_policy: priorityflowcontrolpolicy
+ slow_drain_policy: slowdrainpolicy
+ monitoring_policy: monitoringpolicy
+ storm_control_interface_policy: stormcontrolinterfacepolicy
+ l2_interface_policy: l2interfacepolicy
+ port_security_policy: portsecuritypolicy
+ link_flap_policy: linkflappolicy
+ link_level_flow_control: linklevelflowcontrol
+ mac_sec_interface_policy: macsecinterfacepolicy
+ copp_policy: copppolicy
+ dwdm: dwdmpolicy
+ port_authentication: portauthenticationpolicy
+ poe_interface_policy: poeinterfacepolicy
+ state: present
+ register: intf_policy_leaf_polgrp_all_policy_present
+
+ - name: present assertions (Leaf Access Port) for all the policies.
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_all_policy_present is changed
+ - intf_policy_leaf_polgrp_all_policy_present.previous != []
+ - intf_policy_leaf_polgrp_all_policy_present.current[0].infraAccPortGrp.attributes.name == 'policygroupname_leaf'
+ - intf_policy_leaf_polgrp_all_policy_present.sent.infraAccPortGrp.children.0.infraRsCdpIfPol.attributes.tnCdpIfPolName == 'cdppolicy'
+ - intf_policy_leaf_polgrp_all_policy_present.sent.infraAccPortGrp.children.1.infraRsL2IfPol.attributes.tnL2IfPolName == 'l2interfacepolicy'
+ - intf_policy_leaf_polgrp_all_policy_present.sent.infraAccPortGrp.children.2.infraRsL2PortSecurityPol.attributes.tnL2PortSecurityPolName == 'portsecuritypolicy'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml
new file mode 100644
index 000000000..225e142ba
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_lldp/tasks/main.yml
@@ -0,0 +1,143 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Ensure first lldp interface policy does not exist
+ aci_interface_policy_lldp: &aci_interface_policy_lldp_absent
+ <<: *aci_info
+ name: anstest_policy
+ description: test for lldp interface policy
+ receive_state: false
+ transmit_state: false
+ state: absent
+
+ - name: Ensure second lldp interface policy does not exist
+ aci_interface_policy_lldp: &aci_interface_policy_lldp_2_absent
+ <<: *aci_info
+ name: anstest_policy_2
+ state: absent
+
+ - name: Create first lldp interface policy (check_mode)
+ aci_interface_policy_lldp: &aci_interface_policy_lldp_present
+ <<: *aci_interface_policy_lldp_absent
+ state: present
+ check_mode: true
+ register: cm_add_interface_policy_lldp_1
+
+ - name: Create first lldp interface policy (normal_mode)
+ aci_interface_policy_lldp:
+ <<: *aci_interface_policy_lldp_present
+ register: nm_add_interface_policy_lldp_1
+
+ - name: Create first lldp interface policy again - testing idempotency
+ aci_interface_policy_lldp:
+ <<: *aci_interface_policy_lldp_present
+ register: idempotency_add_interface_policy_lldp_1
+
+ - name: Create second lldp interface policy
+ aci_interface_policy_lldp: &aci_interface_policy_lldp_2_present
+ <<: *aci_interface_policy_lldp_2_absent
+ state: present
+ register: nm_add_interface_policy_lldp_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_interface_policy_lldp_1 is changed
+ - cm_add_interface_policy_lldp_1.previous == []
+ - cm_add_interface_policy_lldp_1.current == []
+ - nm_add_interface_policy_lldp_1 is changed
+ - nm_add_interface_policy_lldp_1.current.0.lldpIfPol.attributes.name == "anstest_policy"
+ - nm_add_interface_policy_lldp_1.current.0.lldpIfPol.attributes.adminRxSt == "disabled"
+ - nm_add_interface_policy_lldp_1.current.0.lldpIfPol.attributes.adminTxSt == "disabled"
+ - idempotency_add_interface_policy_lldp_1 is not changed
+ - nm_add_interface_policy_lldp_2 is changed
+ - nm_add_interface_policy_lldp_2.current.0.lldpIfPol.attributes.name == "anstest_policy_2"
+ - nm_add_interface_policy_lldp_2.current.0.lldpIfPol.attributes.adminRxSt == "enabled"
+ - nm_add_interface_policy_lldp_2.current.0.lldpIfPol.attributes.adminTxSt == "enabled"
+
+ - name: Query all lldp interface policies
+ aci_interface_policy_lldp:
+ <<: *aci_info
+ state: query
+ register: query_all_interface_policy_lldp
+
+ - name: Query first lldp interface policy
+ aci_interface_policy_lldp:
+ <<: *aci_interface_policy_lldp_present
+ state: query
+ register: query_first_interface_policy_lldp
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_interface_policy_lldp is not changed
+ - query_all_interface_policy_lldp.current | length >= 2
+ - '"class/lldpIfPol.json" in query_all_interface_policy_lldp.url'
+ - query_first_interface_policy_lldp is not changed
+ - query_first_interface_policy_lldp.current.0.lldpIfPol.attributes.name == "anstest_policy"
+ - query_first_interface_policy_lldp.current.0.lldpIfPol.attributes.adminRxSt == "disabled"
+ - query_first_interface_policy_lldp.current.0.lldpIfPol.attributes.adminTxSt == "disabled"
+
+ - name: Delete first lldp interface policy (check_mode)
+ aci_interface_policy_lldp:
+ <<: *aci_interface_policy_lldp_present
+ state: absent
+ check_mode: true
+ register: cm_delete_interface_policy_lldp_1
+
+ - name: Delete first lldp interface policy (normal_mode)
+ aci_interface_policy_lldp:
+ <<: *aci_interface_policy_lldp_present
+ state: absent
+ register: nm_delete_interface_policy_lldp_1
+
+ - name: Delete first lldp interface policy again - testing idempotency
+ aci_interface_policy_lldp:
+ <<: *aci_interface_policy_lldp_present
+ state: absent
+ register: idempotency_delete_interface_policy_lldp_1
+
+ - name: Delete second lldp interface policy (normal_mode)
+ aci_interface_policy_lldp:
+ <<: *aci_interface_policy_lldp_2_present
+ state: absent
+ register: nm_delete_interface_policy_lldp_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_interface_policy_lldp_1 is changed
+ - cm_delete_interface_policy_lldp_1.proposed == {}
+ - nm_delete_interface_policy_lldp_1 is changed
+ - nm_delete_interface_policy_lldp_1.previous != []
+ - nm_delete_interface_policy_lldp_1.current == []
+ - idempotency_delete_interface_policy_lldp_1 is not changed
+ - idempotency_delete_interface_policy_lldp_1.previous == []
+ - nm_delete_interface_policy_lldp_2 is changed
+ - nm_delete_interface_policy_lldp_2.previous != []
+ - nm_delete_interface_policy_lldp_2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml
new file mode 100644
index 000000000..7255c14ad
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_mcp/tasks/main.yml
@@ -0,0 +1,255 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Ensure first mcp interface policy does not exist - APIC version >= 5.0
+ aci_interface_policy_mcp: &aci_interface_policy_mcp_absent_5
+ <<: *aci_info
+ name: anstest_policy
+ description: test for mcp interface policy
+ mcp_mode: strict
+ grace_period: 4
+ grace_period_millisec: 500
+ init_delay_time: 5
+ tx_frequence: 2
+ tx_frequence_millisec: 500
+ admin_state: false
+ state: absent
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Ensure first mcp interface policy does not exist
+ aci_interface_policy_mcp: &aci_interface_policy_mcp_absent
+ <<: *aci_info
+ name: anstest_policy
+ description: test for mcp interface policy
+ admin_state: false
+ state: absent
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Ensure second mcp interface policy does not exist
+ aci_interface_policy_mcp: &aci_interface_policy_mcp_2_absent
+ <<: *aci_info
+ name: anstest_policy_2
+ state: absent
+
+ - name: Create first mcp interface policy (check_mode) - APIC version >= 5.0
+ aci_interface_policy_mcp: &aci_interface_policy_mcp_present_5
+ <<: *aci_interface_policy_mcp_absent_5
+ state: present
+ check_mode: true
+ register: cm_add_interface_policy_mcp_1_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Create first mcp interface policy (normal_mode) - APIC version >= 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present_5
+ register: nm_add_interface_policy_mcp_1_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Create first mcp interface policy again - testing idempotency - APIC version >= 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present_5
+ register: idempotency_add_interface_policy_mcp_1_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Create first mcp interface policy (check_mode) - APIC version < 5.0
+ aci_interface_policy_mcp: &aci_interface_policy_mcp_present
+ <<: *aci_interface_policy_mcp_absent
+ state: present
+ check_mode: true
+ register: cm_add_interface_policy_mcp_1
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Create first mcp interface policy (normal_mode) - APIC version < 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present
+ register: nm_add_interface_policy_mcp_1
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Create first mcp interface policy again - testing idempotency - APIC version < 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present
+ register: idempotency_add_interface_policy_mcp_1
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Create second mcp interface policy
+ aci_interface_policy_mcp: &aci_interface_policy_mcp_2_present
+ <<: *aci_interface_policy_mcp_2_absent
+ state: present
+ register: nm_add_interface_policy_mcp_2
+
+ - name: Asserts for creation tasks for first mcp interface policy - APIC version >= 5.0
+ assert:
+ that:
+ - cm_add_interface_policy_mcp_1_5 is changed
+ - cm_add_interface_policy_mcp_1_5.previous == []
+ - cm_add_interface_policy_mcp_1_5.current == []
+ - nm_add_interface_policy_mcp_1_5 is changed
+ - nm_add_interface_policy_mcp_1_5.current.0.mcpIfPol.attributes.name == "anstest_policy"
+ - nm_add_interface_policy_mcp_1_5.current.0.mcpIfPol.attributes.adminSt == "disabled"
+ - idempotency_add_interface_policy_mcp_1_5 is not changed
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Asserts for creation tasks for first mcp interface policy - APIC version < 5.0
+ assert:
+ that:
+ - cm_add_interface_policy_mcp_1 is changed
+ - cm_add_interface_policy_mcp_1.previous == []
+ - cm_add_interface_policy_mcp_1.current == []
+ - nm_add_interface_policy_mcp_1 is changed
+ - nm_add_interface_policy_mcp_1.current.0.mcpIfPol.attributes.name == "anstest_policy"
+ - nm_add_interface_policy_mcp_1.current.0.mcpIfPol.attributes.adminSt == "disabled"
+ - idempotency_add_interface_policy_mcp_1 is not changed
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Asserts for creation tasks for second mcp interface policy
+ assert:
+ that:
+ - nm_add_interface_policy_mcp_2 is changed
+ - nm_add_interface_policy_mcp_2.current.0.mcpIfPol.attributes.name == "anstest_policy_2"
+ - nm_add_interface_policy_mcp_2.current.0.mcpIfPol.attributes.adminSt == "enabled"
+
+ - name: Query all mcp interface policies
+ aci_interface_policy_mcp:
+ <<: *aci_info
+ state: query
+ register: query_all_interface_policy_mcp
+
+ - name: Query first mcp interface policy
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present_5
+ state: query
+ register: query_first_interface_policy_mcp_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Query first mcp interface policy
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present
+ state: query
+ register: query_first_interface_policy_mcp
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_interface_policy_mcp is not changed
+ - query_all_interface_policy_mcp.current | length >= 2
+ - '"class/mcpIfPol.json" in query_all_interface_policy_mcp.url'
+
+ - name: Asserts for individual query tasks - APIC version >= 5.0
+ assert:
+ that:
+ - query_first_interface_policy_mcp_5.current.0.mcpIfPol.attributes.name == "anstest_policy"
+ - query_first_interface_policy_mcp_5.current.0.mcpIfPol.attributes.adminSt == "disabled"
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Asserts for individual query tasks - APIC version < 5.0
+ assert:
+ that:
+ - query_first_interface_policy_mcp.current.0.mcpIfPol.attributes.name == "anstest_policy"
+ - query_first_interface_policy_mcp.current.0.mcpIfPol.attributes.adminSt == "disabled"
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Delete first mcp interface policy (check_mode) - APIC version >= 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present_5
+ state: absent
+ check_mode: true
+ register: cm_delete_interface_policy_mcp_1_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Delete first mcp interface policy (normal_mode) - APIC version >= 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present_5
+ state: absent
+ register: nm_delete_interface_policy_mcp_1_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Delete first mcp interface policy again - testing idempotency - APIC version >= 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present_5
+ state: absent
+ register: idempotency_delete_interface_policy_mcp_1_5
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Delete first mcp interface policy (check_mode) - APIC version < 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present
+ state: absent
+ check_mode: true
+ register: cm_delete_interface_policy_mcp_1
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Delete first mcp interface policy (normal_mode) - APIC version < 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present
+ state: absent
+ register: nm_delete_interface_policy_mcp_1
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Delete first mcp interface policy again - testing idempotency - APIC version < 5.0
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_present
+ state: absent
+ register: idempotency_delete_interface_policy_mcp_1
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Delete second mcp interface policy (normal_mode)
+ aci_interface_policy_mcp:
+ <<: *aci_interface_policy_mcp_2_present
+ state: absent
+ register: nm_delete_interface_policy_mcp_2
+
+ - name: Asserts for first mcp interface policy deletion tasks - APIC version >= 5.0
+ assert:
+ that:
+ - cm_delete_interface_policy_mcp_1_5 is changed
+ - cm_delete_interface_policy_mcp_1_5.proposed == {}
+ - nm_delete_interface_policy_mcp_1_5 is changed
+ - nm_delete_interface_policy_mcp_1_5.previous != []
+ - nm_delete_interface_policy_mcp_1_5.current == []
+ - idempotency_delete_interface_policy_mcp_1_5 is not changed
+ - idempotency_delete_interface_policy_mcp_1_5.previous == []
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+ - name: Asserts for first mcp interface policy deletion tasks - APIC version < 5.0
+ assert:
+ that:
+ - cm_delete_interface_policy_mcp_1 is changed
+ - cm_delete_interface_policy_mcp_1.proposed == {}
+ - nm_delete_interface_policy_mcp_1 is changed
+ - nm_delete_interface_policy_mcp_1.previous != []
+ - nm_delete_interface_policy_mcp_1.current == []
+ - idempotency_delete_interface_policy_mcp_1 is not changed
+ - idempotency_delete_interface_policy_mcp_1.previous == []
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+ - name: Asserts for second mcp interface policy deletion tasks
+ assert:
+ that:
+ - nm_delete_interface_policy_mcp_2.previous != []
+ - nm_delete_interface_policy_mcp_2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml
index 96a5472f0..71e096435 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml
@@ -8,47 +8,33 @@
msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_password }}'
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
# CLEAN ENVIRONMENT
- name: 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
tenant: ansible_test
- state: present
- register: tenant_present
- name: Remove OSPF interface policy
cisco.aci.aci_interface_policy_ospf: &interface_policy_ospf_absent
- 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") }}'
- tenant: ansible_test
+ <<: *aci_tenant_present
ospf: ansible_ospf
state: absent
-
# ADD OSPF INTERFACE POLICY
- name: Add ospf interface policy (check_mode)
cisco.aci.aci_interface_policy_ospf: &interface_policy_ospf_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: '{{ aci_output_level | default("info") }}'
- tenant: ansible_test
- ospf: ansible_ospf
+ <<: *interface_policy_ospf_absent
state: present
check_mode: true
register: cm_add_ospf_interface_policy
@@ -70,47 +56,220 @@
assert:
that:
- cm_add_ospf_interface_policy is changed
+ - cm_add_ospf_interface_policy.current == []
+ - cm_add_ospf_interface_policy.proposed.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - cm_add_ospf_interface_policy.proposed.ospfIfPol.attributes.name == "ansible_ospf"
- nm_add_ospf_interface_policy is changed
- - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_ospf_interface_policy.previous == []
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.descr == ""
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.cost == "unspecified"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.ctrl == ""
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.deadIntvl == "40"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.helloIntvl == "10"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.nwT == "unspecified"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.pfxSuppress == "inherit"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.prio == "1"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.rexmitIntvl == "5"
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.xmitDelay == "1"
- cm_add_ospf_interface_policy_again is not changed
- nm_add_ospf_interface_policy_again is not changed
-
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.descr == ""
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.cost == "unspecified"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.ctrl == ""
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.deadIntvl == "40"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.helloIntvl == "10"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.nwT == "unspecified"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.pfxSuppress == "inherit"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.prio == "1"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.rexmitIntvl == "5"
+ - nm_add_ospf_interface_policy_again.previous.0.ospfIfPol.attributes.xmitDelay == "1"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.descr == ""
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.cost == "unspecified"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.ctrl == ""
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.deadIntvl == "40"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.helloIntvl == "10"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.nwT == "unspecified"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.pfxSuppress == "inherit"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.prio == "1"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.rexmitIntvl == "5"
+ - nm_add_ospf_interface_policy_again.current.0.ospfIfPol.attributes.xmitDelay == "1"
# CHANGE OSPF INTERFACE POLICY
- name: Change description of ospf interface policy (check_mode)
- cisco.aci.aci_interface_policy_ospf:
+ cisco.aci.aci_interface_policy_ospf: &change_osp_interface_policy
<<: *interface_policy_ospf_present
- description: Ansible test ospf interface policy
+ description: Ansible test ospf interface policy changed
+ network_type: bcast
+ cost: 11
+ controls: mtu-ignore
+ dead_interval: 12
+ hello_interval: 13
+ prefix_suppression: disable
+ priority: 14
+ retransmit_interval: 15
+ transmit_delay: 16
check_mode: true
register: cm_add_ospf_descr
- name: Change description of ospf interface policy (normal mode)
cisco.aci.aci_interface_policy_ospf:
- <<: *interface_policy_ospf_present
- description: Ansible test ospf interface policy
+ <<: *change_osp_interface_policy
register: nm_add_ospf_descr
- name: Change description of ospf interface policy again (check_mode)
cisco.aci.aci_interface_policy_ospf:
- <<: *interface_policy_ospf_present
- description: Ansible test ospf interface policy
+ <<: *change_osp_interface_policy
check_mode: true
register: cm_add_ospf_descr_again
- name: Change description of ospf interface policy again (normal mode)
cisco.aci.aci_interface_policy_ospf:
- <<: *interface_policy_ospf_present
- description: Ansible test ospf interface policy
+ <<: *change_osp_interface_policy
register: nm_add_ospf_descr_again
- name: Verify add_ospf_descr
assert:
that:
- cm_add_ospf_descr is changed
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.descr == ""
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.cost == "unspecified"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.ctrl == ""
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.deadIntvl == "40"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.helloIntvl == "10"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.nwT == "unspecified"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.pfxSuppress == "inherit"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.prio == "1"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.rexmitIntvl == "5"
+ - cm_add_ospf_descr.previous.0.ospfIfPol.attributes.xmitDelay == "1"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.descr == "Ansible test ospf interface policy changed"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.name == "ansible_ospf"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.cost == "11"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.ctrl == "mtu-ignore"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.deadIntvl == "12"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.helloIntvl == "13"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.nwT == "bcast"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.pfxSuppress == "disable"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.prio == "14"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.rexmitIntvl == "15"
+ - cm_add_ospf_descr.proposed.ospfIfPol.attributes.xmitDelay == "16"
- nm_add_ospf_descr is changed
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.descr == ""
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.cost == "unspecified"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.ctrl == ""
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.deadIntvl == "40"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.helloIntvl == "10"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.nwT == "unspecified"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.pfxSuppress == "inherit"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.prio == "1"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.rexmitIntvl == "5"
+ - nm_add_ospf_descr.previous.0.ospfIfPol.attributes.xmitDelay == "1"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.descr == "Ansible test ospf interface policy changed"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.cost == "11"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.ctrl == "mtu-ignore"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.deadIntvl == "12"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.helloIntvl == "13"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.nwT == "bcast"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.pfxSuppress == "disable"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.prio == "14"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.rexmitIntvl == "15"
+ - nm_add_ospf_descr.current.0.ospfIfPol.attributes.xmitDelay == "16"
- cm_add_ospf_descr_again is not changed
- nm_add_ospf_descr_again is not changed
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.descr == "Ansible test ospf interface policy changed"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.cost == "11"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.ctrl == "mtu-ignore"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.deadIntvl == "12"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.helloIntvl == "13"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.nwT == "bcast"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.pfxSuppress == "disable"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.prio == "14"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.rexmitIntvl == "15"
+ - nm_add_ospf_descr_again.previous.0.ospfIfPol.attributes.xmitDelay == "16"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.annotation == "orchestrator:ansible"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.descr == "Ansible test ospf interface policy changed"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.name == "ansible_ospf"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.cost == "11"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.ctrl == "mtu-ignore"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.deadIntvl == "12"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.helloIntvl == "13"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.nwT == "bcast"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.pfxSuppress == "disable"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.prio == "14"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.rexmitIntvl == "15"
+ - nm_add_ospf_descr_again.current.0.ospfIfPol.attributes.xmitDelay == "16"
+
+- name: Change cost of ospf interface policy
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_present
+ cost: 451
+ ignore_errors: true
+ register: err_change_ospf_cost
+
+- name: Change dead_interval of ospf interface policy
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_present
+ dead_interval: 65539
+ ignore_errors: true
+ register: err_change_ospf_dead_interval
+
+- name: Change hello_interval of ospf interface policy
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_present
+ hello_interval: 65538
+ ignore_errors: true
+ register: err_change_ospf_hello_interval
+- name: Change priority of ospf interface policy
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_present
+ priority: 256
+ ignore_errors: true
+ register: err_change_ospf_priority
+
+- name: Change retransmit_interval of ospf interface policy
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_present
+ retransmit_interval: 65537
+ ignore_errors: true
+ register: err_change_ospf_retransmit_interval
+
+- name: Change transmit_delay of ospf interface policy
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_present
+ transmit_delay: 451
+ ignore_errors: true
+ register: err_change_ospf_transmit_delay
+
+- name: Verify cost change and error input values
+ assert:
+ that:
+ - err_change_ospf_cost is not changed
+ - err_change_ospf_cost.msg == "Parameter 'cost' is only valid in range between 1 and 450."
+ - err_change_ospf_dead_interval is not changed
+ - err_change_ospf_dead_interval.msg == "Parameter 'dead_interval' is only valid in range between 1 and 65536."
+ - err_change_ospf_hello_interval is not changed
+ - err_change_ospf_hello_interval.msg == "Parameter 'hello_interval' is only valid in range between 1 and 65536."
+ - err_change_ospf_priority is not changed
+ - err_change_ospf_priority.msg == "Parameter 'priority' is only valid in range between 1 and 255."
+ - err_change_ospf_retransmit_interval is not changed
+ - err_change_ospf_retransmit_interval.msg == "Parameter 'retransmit_interval' is only valid in range between 1 and 65536."
+ - err_change_ospf_transmit_delay is not changed
+ - err_change_ospf_transmit_delay.msg == "Parameter 'transmit_delay' is only valid in range between 1 and 450."
# ADD OSPF INTERFACE POLICY AGAIN
- name: Add ospf interface policy again with no description (check_mode)
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml
new file mode 100644
index 000000000..36c84b30f
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_channel/tasks/main.yml
@@ -0,0 +1,174 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Ensure first port channel interface policy does not exist
+ aci_interface_policy_port_channel: &aci_interface_policy_port_channel_absent
+ <<: *aci_info
+ name: anstest_policy
+ description: test for port channel interface policy
+ max_links: 8
+ min_links: 2
+ mode: active
+ fast_select: false
+ graceful_convergence: false
+ load_defer: true
+ suspend_individual: false
+ symmetric_hash: true
+ state: absent
+
+ - name: Ensure second port channel interface policy does not exist
+ aci_interface_policy_port_channel: &aci_interface_policy_port_channel_2_absent
+ <<: *aci_info
+ name: anstest_policy_2
+ fast_select: true
+ graceful_convergence: true
+ suspend_individual: true
+ state: absent
+
+ - name: Create first port channel interface policy (check_mode)
+ aci_interface_policy_port_channel: &aci_interface_policy_port_channel_present
+ <<: *aci_interface_policy_port_channel_absent
+ state: present
+ check_mode: true
+ register: cm_add_interface_policy_port_channel_1
+
+ - name: Create first port channel interface policy (normal_mode)
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ register: nm_add_interface_policy_port_channel_1
+
+ - name: Create first port channel interface policy again - testing idempotency
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ register: idempotency_add_interface_policy_port_channel_1
+
+ - name: Create second port channel interface policy
+ aci_interface_policy_port_channel: &aci_interface_policy_port_channel_2_present
+ <<: *aci_interface_policy_port_channel_2_absent
+ state: present
+ register: nm_add_interface_policy_port_channel_2
+
+ - name: Modify first port channel interface policy with max links above 16 - testing failure message
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ max_links: 17
+ ignore_errors: true
+ register: nm_policy_port_channel_max_links_failure
+
+ - name: Modify first port channel interface policy with min links bellow 1 - testing failure message
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ min_links: 0
+ ignore_errors: true
+ register: nm_policy_port_channel_min_links_failure
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_interface_policy_port_channel_1 is changed
+ - cm_add_interface_policy_port_channel_1.previous == []
+ - cm_add_interface_policy_port_channel_1.current == []
+ - nm_add_interface_policy_port_channel_1 is changed
+ - nm_add_interface_policy_port_channel_1.current.0.lacpLagPol.attributes.name == "anstest_policy"
+ - nm_add_interface_policy_port_channel_1.current.0.lacpLagPol.attributes.ctrl == "load-defer,symmetric-hash"
+ - nm_add_interface_policy_port_channel_1.current.0.lacpLagPol.attributes.maxLinks == "8"
+ - nm_add_interface_policy_port_channel_1.current.0.lacpLagPol.attributes.minLinks == "2"
+ - nm_add_interface_policy_port_channel_1.current.0.lacpLagPol.attributes.mode == "active"
+ - idempotency_add_interface_policy_port_channel_1 is not changed
+ - nm_add_interface_policy_port_channel_2 is changed
+ - nm_add_interface_policy_port_channel_2.current.0.lacpLagPol.attributes.name == "anstest_policy_2"
+ - nm_add_interface_policy_port_channel_2.current.0.lacpLagPol.attributes.ctrl == "fast-sel-hot-stdby,graceful-conv,susp-individual"
+ - nm_add_interface_policy_port_channel_2.current.0.lacpLagPol.attributes.maxLinks == "16"
+ - nm_add_interface_policy_port_channel_2.current.0.lacpLagPol.attributes.minLinks == "1"
+ - nm_add_interface_policy_port_channel_2.current.0.lacpLagPol.attributes.mode == "off"
+ - nm_policy_port_channel_max_links_failure.msg == "The \"max_links\" must be a value between 1 and 16"
+ - nm_policy_port_channel_min_links_failure.msg == "The \"min_links\" must be a value between 1 and 16"
+
+ - name: Query all port channel interface policies
+ aci_interface_policy_port_channel:
+ <<: *aci_info
+ state: query
+ register: query_all_interface_policy_port_channel
+
+ - name: Query first port channel interface policy
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ state: query
+ register: query_first_interface_policy_port_channel
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_interface_policy_port_channel is not changed
+ - query_all_interface_policy_port_channel.current | length >= 2
+ - '"class/lacpLagPol.json" in query_all_interface_policy_port_channel.url'
+ - query_first_interface_policy_port_channel is not changed
+ - query_first_interface_policy_port_channel.current.0.lacpLagPol.attributes.name == "anstest_policy"
+ - query_first_interface_policy_port_channel.current.0.lacpLagPol.attributes.ctrl == "load-defer,symmetric-hash"
+ - query_first_interface_policy_port_channel.current.0.lacpLagPol.attributes.maxLinks == "8"
+ - query_first_interface_policy_port_channel.current.0.lacpLagPol.attributes.minLinks == "2"
+ - query_first_interface_policy_port_channel.current.0.lacpLagPol.attributes.mode == "active"
+
+ - name: Delete first port channel interface policy (check_mode)
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ state: absent
+ check_mode: true
+ register: cm_delete_interface_policy_port_channel_1
+
+ - name: Delete first port channel interface policy (normal_mode)
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ state: absent
+ register: nm_delete_interface_policy_port_channel_1
+
+ - name: Delete first port channel interface policy again - testing idempotency
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_present
+ state: absent
+ register: idempotency_delete_interface_policy_port_channel_1
+
+ - name: Delete second port channel interface policy (normal_mode)
+ aci_interface_policy_port_channel:
+ <<: *aci_interface_policy_port_channel_2_present
+ state: absent
+ register: nm_delete_interface_policy_port_channel_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_interface_policy_port_channel_1 is changed
+ - cm_delete_interface_policy_port_channel_1.proposed == {}
+ - nm_delete_interface_policy_port_channel_1 is changed
+ - nm_delete_interface_policy_port_channel_1.previous != []
+ - nm_delete_interface_policy_port_channel_1.current == []
+ - idempotency_delete_interface_policy_port_channel_1 is not changed
+ - idempotency_delete_interface_policy_port_channel_1.previous == []
+ - nm_delete_interface_policy_port_channel_2 is changed
+ - nm_delete_interface_policy_port_channel_2.previous != []
+ - nm_delete_interface_policy_port_channel_2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml
new file mode 100644
index 000000000..fec8415a3
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spine_policy_group/tasks/main.yml
@@ -0,0 +1,130 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Anvitha Jain <anvjain@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+
+ # CLEAN ENVIRONMENT
+ - name: Making sure interface_policy_spine_policy_group doesn't exist at beginning of test (Spine Access Port)
+ cisco.aci.aci_interface_policy_spine_policy_group: &spine_absent
+ <<: *aci_info
+ policy_group: spine_pg_test
+ state: absent
+
+ # ADD Spine Policy Group
+ - name: Adding a interface policy spine policy group - check mode works
+ cisco.aci.aci_interface_policy_spine_policy_group: &spine_present
+ <<: *aci_info
+ policy_group: spine_pg_test
+ link_level_policy: link_level_policy_test
+ link_flap_policy: link_flap_policy_test
+ cdp_policy: cdp_policy_test
+ mac_sec_policy: mac_sec_policy_test
+ attached_entity_profile: policy_group_aep
+ state: present
+ check_mode: yes
+ register: intf_policy_spine_polgrp_check_mode_present
+
+ - name: Adding a interface policy spine policy group - creation works
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *spine_present
+ register: intf_policy_spine_polgrp_present
+
+ - name: Adding a interface policy spine policy group - idempotency works
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *spine_present
+ register: intf_policy_spine_polgrp_idempotent
+
+ # UPDATE Spine Policy Group
+ - name: Adding a interface policy spine policy group description - update works
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *spine_present
+ description: policygroup description
+ register: intf_policy_spine_polgrp_update
+
+ - name: Verify present assertions for Spine Policy Group
+ assert:
+ that:
+ - intf_policy_spine_polgrp_check_mode_present is changed
+ - intf_policy_spine_polgrp_present is changed
+ - intf_policy_spine_polgrp_present.previous == []
+ - intf_policy_spine_polgrp_present.current[0].infraSpAccPortGrp.attributes.name == 'spine_pg_test'
+ - intf_policy_spine_polgrp_present.current[0].infraSpAccPortGrp.children.0.infraRsLinkFlapPol.attributes.tnFabricLinkFlapPolName == 'link_flap_policy_test'
+ - intf_policy_spine_polgrp_present.current[0].infraSpAccPortGrp.children.1.infraRsMacsecIfPol.attributes.tnMacsecIfPolName == 'mac_sec_policy_test'
+ - intf_policy_spine_polgrp_present.current[0].infraSpAccPortGrp.children.2.infraRsAttEntP.attributes.tDn == 'uni/infra/attentp-policy_group_aep'
+ - intf_policy_spine_polgrp_present.current[0].infraSpAccPortGrp.children.3.infraRsHIfPol.attributes.tnFabricHIfPolName == 'link_level_policy_test'
+ - intf_policy_spine_polgrp_present.current[0].infraSpAccPortGrp.children.4.infraRsCdpIfPol.attributes.tnCdpIfPolName == 'cdp_policy_test'
+ - intf_policy_spine_polgrp_present.current[0].infraSpAccPortGrp.attributes.annotation == 'orchestrator:ansible'
+ - intf_policy_spine_polgrp_idempotent is not changed
+ - intf_policy_spine_polgrp_idempotent.sent == {}
+ - intf_policy_spine_polgrp_update is changed
+ - intf_policy_spine_polgrp_update.current[0].infraSpAccPortGrp.attributes.descr == 'policygroup description'
+
+ # QUERY Spine Policy Group
+ - name: Query all interface policy spine policy groups
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *aci_info
+ state: query
+ register: query_all_spine_policy_groups
+
+ - name: Query interface policy spine policy group
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *aci_info
+ policy_group: spine_pg_test
+ state: query
+ register: query_spine_policy_group
+
+ - name: Verify query assertions for Spine Policy Group
+ assert:
+ that:
+ - query_spine_policy_group is not changed
+ - query_spine_policy_group.current[0] | length >= 1
+ - query_all_spine_policy_groups is not changed
+
+ - name: Remove interface policy spine policy group - check mode
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *spine_absent
+ check_mode: yes
+ register: intf_policy_spine_polgrp_check_mode_absent
+
+ - name: Remove interface policy spine policy group - delete works
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *spine_absent
+ register: intf_policy_spine_polgrp_absent
+
+ - name: Remove interface policy spine policy group - idempotency works
+ cisco.aci.aci_interface_policy_spine_policy_group:
+ <<: *spine_absent
+ register: intf_policy_spine_polgrp_absent_idempotent
+
+ - name: Verify absent assertions for Spine Policy Group
+ assert:
+ that:
+ - intf_policy_spine_polgrp_check_mode_absent is changed
+ - intf_policy_spine_polgrp_check_mode_absent.previous != []
+ - intf_policy_spine_polgrp_absent is changed
+ - intf_policy_spine_polgrp_absent.previous == intf_policy_spine_polgrp_absent.previous
+ - intf_policy_spine_polgrp_absent_idempotent is not changed
+ - intf_policy_spine_polgrp_absent_idempotent.previous == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml
new file mode 100644
index 000000000..65474048c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out/tasks/main.yml
@@ -0,0 +1,270 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Remove the ansible_l3out
+ aci_l3out: &aci_l3out_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ description: L3Out for ansible_tenant tenant
+ domain: ansible_dom
+ vrf: ansible_vrf
+ state: absent
+
+ - name: Remove the second ansible_l3out
+ aci_l3out: &aci_l3out_2_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out_2
+ description: Second L3Out
+ domain: ansible_dom
+ vrf: ansible_vrf
+ l3protocol: [ ospf, bgp ]
+ state: absent
+
+ - name: Add a new L3Out (check_mode)
+ aci_l3out: &aci_l3out_present
+ <<: *aci_l3out_absent
+ state: present
+ check_mode: true
+ register: cm_add_l3out
+
+ - name: Add a new L3Out (normal_mode)
+ aci_l3out:
+ <<: *aci_l3out_present
+ register: nm_add_l3out
+
+ - name: create L3Out again - testing idempotency
+ aci_l3out:
+ <<: *aci_l3out_present
+ register: create_idempotency
+
+ - name: Add the second ansible_l3out
+ aci_l3out:
+ <<: *aci_l3out_2_absent
+ state: present
+ register: cm_add_l3out_2
+
+ - name: asserts for l3out creation tasks
+ assert:
+ that:
+ - cm_add_l3out is changed
+ - cm_add_l3out.previous == []
+ - cm_add_l3out.current == []
+ - nm_add_l3out is changed
+ - nm_add_l3out.current.0.l3extOut.attributes.descr == cm_add_l3out.sent.l3extOut.attributes.descr == "L3Out for ansible_tenant tenant"
+ - nm_add_l3out.current.0.l3extOut.attributes.name == cm_add_l3out.sent.l3extOut.attributes.name == "ansible_l3out"
+ - create_idempotency is not changed
+
+ - name: Add export and import to route_control
+ aci_l3out:
+ <<: *aci_l3out_present
+ route_control: [ import, export ]
+ register: nm_add_l3out_import_export
+
+ - name: Add export to route_control
+ aci_l3out:
+ <<: *aci_l3out_present
+ route_control: export
+ register: nm_add_l3out_export
+
+ - name: Add just import to route_control - testing failure message
+ aci_l3out:
+ <<: *aci_l3out_present
+ route_control: import
+ register: nm_add_l3out_import_error
+ ignore_errors: true
+
+ - name: asserts for l3out route control tasks
+ assert:
+ that:
+ - nm_add_l3out_import_export is changed
+ - nm_add_l3out_import_export.current.0.l3extOut.attributes.enforceRtctrl == "export,import"
+ - nm_add_l3out_export is changed
+ - nm_add_l3out_export.current.0.l3extOut.attributes.enforceRtctrl == "export"
+ - nm_add_l3out_import_error.msg == "The route_control parameter is invalid{{':'}} allowed options are export or import,export only"
+
+ - name: Add BGP protocol
+ aci_l3out:
+ <<: *aci_l3out_present
+ l3protocol: bgp
+ register: nm_add_l3out_bgp
+
+ - name: Add BGP protocol again - testing L3protocol changes
+ aci_l3out:
+ <<: *aci_l3out_present
+ l3protocol: bgp
+ register: nm_add_l3out_bgp_again
+
+ - name: Add PIM protocol, ospf_spec and asn - testing warning message for asn
+ aci_l3out:
+ <<: *aci_l3out_present
+ l3protocol: pim
+ asn: 1
+ register: nm_add_l3out_pim
+
+ - name: Add EIGRP protocol - testing warning message for OSPF spec
+ aci_l3out:
+ <<: *aci_l3out_present
+ l3protocol: eigrp
+ asn: 1
+ ospf:
+ description: OSPF warnings message works
+ register: nm_add_l3out_eigrp
+
+ - name: remove asn - testing failure message
+ aci_l3out:
+ <<: *aci_l3out_present
+ l3protocol: eigrp
+ asn: null
+ register: add_l3out_without_asn
+ ignore_errors: true
+
+ - name: remove protocol - testing static protocol
+ aci_l3out:
+ <<: *aci_l3out_present
+ l3protocol: static
+ register: nm_remove_l3protocol
+
+ - name: asserts for l3out protocols tasks
+ assert:
+ that:
+ - nm_add_l3out_bgp is changed
+ - nm_add_l3out_bgp_again is changed
+ - nm_add_l3out_pim is changed
+ - nm_add_l3out_pim.warnings.0 == "Parameter 'asn' is only applicable when l3protocol is 'eigrp'. The ASN will be ignored"
+ - nm_add_l3out_eigrp is changed
+ - nm_add_l3out_eigrp.current.0.l3extOut.children.0.eigrpExtP.attributes.asn == "1"
+ - nm_add_l3out_eigrp.warnings.0 == "Parameter 'ospf' is only applicable when l3protocol is 'ospf'. The OPSF specifications will be ignored"
+ - add_l3out_without_asn.msg == "Parameter 'asn' is required when l3protocol is 'eigrp'"
+ - nm_remove_l3protocol is changed
+
+ - name: Add OSPF protocol
+ aci_l3out:
+ <<: *aci_l3out_present
+ l3protocol: ospf
+ ospf:
+ area_cost: 1
+ area_ctrl: [ summary, redistribute ]
+ area_id: 0.0.0.2
+ area_type: regular
+ multipod_internal: no
+ description: test for ospf protocol
+ register: nm_add_l3out_ospf
+
+ - name: asserts for l3out OSPF protocol tasks
+ assert:
+ that:
+ - nm_add_l3out_ospf is changed
+ - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.areaCost == "1"
+ - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.areaCtrl == "redistribute,summary"
+ - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.areaId == "0.0.0.2"
+ - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.areaType == "regular"
+ - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.descr == "test for ospf protocol"
+ - nm_add_l3out_ospf.current.0.l3extOut.children.2.ospfExtP.attributes.multipodInternal == "no"
+
+ - name: get ansible_l3out
+ aci_l3out:
+ <<: *aci_l3out_present
+ state: query
+ register: get_l3out
+
+ - name: get all l3outs in ansible_tenant
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: query
+ register: get_all_l3out_ansible_tenant
+
+ - name: get all l3outs
+ aci_l3out:
+ <<: *aci_info
+ state: query
+ register: get_all_l3out
+
+ - name: asserts query tasks
+ assert:
+ that:
+ - get_l3out is not changed
+ - '"rsp-subtree=full&rsp-subtree-class=bgpExtP,eigrpExtP,l3extRsEctx,l3extRsL3DomAtt,ospfExtP,pimExtP" in get_l3out.filter_string'
+ - '"tn-ansible_tenant/out-ansible_l3out.json" in get_l3out.url'
+ - get_all_l3out_ansible_tenant is not changed
+ - '"ospfExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.0.l3extOut.children.2'
+ - '"ospfExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.1.l3extOut.children.2'
+ - '"bgpExtP" in get_all_l3out_ansible_tenant.current.0.fvTenant.children.1.l3extOut.children.3'
+ - get_all_l3out is not changed
+ - get_all_l3out.current | length >= 2
+
+ - name: delete l3out (check_mode)
+ aci_l3out:
+ <<: *aci_l3out_present
+ state: absent
+ check_mode: true
+ register: delete_cm
+
+ - name: delete l3out (normal_mode)
+ aci_l3out:
+ <<: *aci_l3out_present
+ state: absent
+ register: delete_l3out
+
+ - name: delete l3out again - testing idempotency
+ aci_l3out:
+ <<: *aci_l3out_present
+ state: absent
+ register: delete_idempotency
+
+ - name: asserts for deletion tasks
+ assert:
+ that:
+ - delete_cm is changed
+ - delete_cm.proposed == {}
+ - delete_l3out is changed
+ - delete_l3out.previous != []
+ - delete_l3out.method == "DELETE"
+ - delete_idempotency is not changed
+ - delete_idempotency.previous == []
+
+ - name: Delete the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml
index 4e1784a6a..8ed2daee3 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml
@@ -201,6 +201,7 @@
address_type_controls:
- af-ucast
ttl: 2
+ local_as_number_config: "replace-as"
state: present
register: add_eth_bgp_peer
when: version.current.0.topSystem.attributes.version is version('4', '>=')
@@ -239,6 +240,8 @@
- add_eth_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
- add_eth_bgp_peer.current.0.bgpPeerP.attributes.ttl == "2"
- add_eth_bgp_peer.current.0.bgpPeerP.attributes.annotation == 'orchestrator:ansible'
+ - add_eth_bgp_peer.current.0.bgpPeerP.children.0.bgpLocalAsnP.attributes.asnPropagate == "replace-as"
+ - add_eth_bgp_peer.current.0.bgpPeerP.children.0.bgpLocalAsnP.attributes.localAsn == "0"
when: version.current.0.topSystem.attributes.version is version('4', '>=')
- name: verify BGP peer has been created with correct attributes (version < 4)
@@ -255,7 +258,7 @@
- name: verify remote AS object has been created correctly
assert:
that:
- - add_eth_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ - add_eth_bgp_peer.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65456"
when: version.current.0.topSystem.attributes.version is version('4', '>=')
- name: verify remote AS object has been created correctly
@@ -340,7 +343,7 @@
- name: verify remote AS object is still correct (version >= 4)
assert:
that:
- - add_eth_bgp_peer_again.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65456"
when: version.current.0.topSystem.attributes.version is version('4', '>=')
- name: verify remote AS object his still correct (version < 4)
@@ -376,6 +379,8 @@
allow_self_as_count: 3
ttl: 4
admin_state: disabled
+ local_as_number: 101
+ local_as_number_config: "dual-as"
state: present
register: update_eth_bgp_peer
when: version.current.0.topSystem.attributes.version is version('4', '>=')
@@ -419,6 +424,8 @@
- update_eth_bgp_peer.current.0.bgpPeerP.attributes.ttl == "4"
- update_eth_bgp_peer.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
- update_eth_bgp_peer.current.0.bgpPeerP.attributes.privateASctrl == "remove-exclusive"
+ - update_eth_bgp_peer.current.0.bgpPeerP.children.0.bgpLocalAsnP.attributes.asnPropagate == "dual-as"
+ - update_eth_bgp_peer.current.0.bgpPeerP.children.0.bgpLocalAsnP.attributes.localAsn == "101"
when: version.current.0.topSystem.attributes.version is version('4', '>=')
- name: verify BGP peer has been updated with correct attributes (version < 4)
@@ -437,7 +444,7 @@
- name: verify remote AS object has been updated correctly (version >= 4)
assert:
that:
- - update_eth_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ - update_eth_bgp_peer.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65457"
when: version.current.0.topSystem.attributes.version is version('4', '>=')
- name: verify remote AS object has been updated correctly (version < 4)
@@ -508,7 +515,7 @@
- name: verify BGP remote AS (version >= 4)
assert:
that:
- - query_eth_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ - query_eth_bgp_peer.current.0.bgpPeerP.children.2.bgpAsP.attributes.asn == "65457"
when: version.current.0.topSystem.attributes.version is version('4', '>=')
- name: verify BGP remote AS (version < 4)
@@ -641,6 +648,8 @@
profile: "anstest_export"
direction: "export"
l3out: "anstest_l3out"
+ local_as_number_config: "dual-as"
+ local_as_number: 100
state: present
check_mode: true
register: cm_ln_rtctrl_present
@@ -668,6 +677,8 @@
- nm_ln_rtctrl_present.previous | length == 0
- nm_ln_rtctrl_present.current.0.bgpPeerP.attributes.addr == "192.168.50.3"
- nm_ln_rtctrl_present.current.0.bgpPeerP.children | length >= 2
+ - nm_ln_rtctrl_present.current.0.bgpPeerP.children.2.bgpLocalAsnP.attributes.asnPropagate == "dual-as"
+ - nm_ln_rtctrl_present.current.0.bgpPeerP.children.2.bgpLocalAsnP.attributes.localAsn == "100"
- name: Add BGP Peer to the Node Profile level (version >= 4) - normal mode - idempotency works
aci_l3out_bgp_peer:
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml
new file mode 100644
index 000000000..85b43726c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_protocol_profile/tasks/main.yml
@@ -0,0 +1,184 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a new l3out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ description: Ansible L3Out for ansible_tenant tenant
+ domain: ansible_dom
+ vrf: ansible_vrf
+ state: present
+
+ - name: Add a new logical node profile
+ aci_l3out_logical_node_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile_1
+ description: Ansible Logical Node Profile 1 for ansible_l3out L3Out
+ state: present
+
+ - name: Add a second logical node profile
+ aci_l3out_logical_node_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile_2
+ description: Ansible Logical Node Profile 2 for ansible_l3out L3Out
+ state: present
+
+ - name: Add a new BGP timers policy
+ aci_bgp_timers_policy:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bgp_timers_policy: ansible_bgp_timers_policy
+ description: Ansible BGP timers policy for ansible_tenant tenant
+ state: present
+
+ - name: Add a new BGP protocol profile
+ aci_bgp_best_path_policy:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bgp_best_path_policy: ansible_bgp_best_path_policy
+ description: Ansible BGP protocol profile for ansible_tenant tenant
+ state: present
+
+ - name: Add a BGP protocol profile (check_mode)
+ aci_l3out_bgp_protocol_profile: &aci_l3out_bgp_protocol_profile_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile_1
+ bgp_timers_policy: ansible_bgp_timers_policy
+ bgp_best_path_policy: ansible_bgp_best_path_policy
+ state: present
+ check_mode: true
+ register: cm_add_bgp_protocol_profile
+
+ - name: Add a BGP protocol profile (normal_mode)
+ aci_l3out_bgp_protocol_profile:
+ <<: *aci_l3out_bgp_protocol_profile_present
+ register: nm_add_bgp_protocol_profile
+
+ - name: Add the first BGP protocol profile again - testing idempotency
+ aci_l3out_bgp_protocol_profile:
+ <<: *aci_l3out_bgp_protocol_profile_present
+ register: nm_add_bgp_protocol_profile_idempotency
+
+ - name: Add a second BGP protocol profile (normal_mode)
+ aci_l3out_bgp_protocol_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile_2
+ state: present
+ register: nm_add_bgp_protocol_profile_2
+
+ - name: Asserts for BGP protocol profiles creation tasks
+ assert:
+ that:
+ - cm_add_bgp_protocol_profile is changed
+ - cm_add_bgp_protocol_profile.previous == []
+ - cm_add_bgp_protocol_profile.current == []
+ - nm_add_bgp_protocol_profile is changed
+ - nm_add_bgp_protocol_profile.current.0.bgpProtP.children.0.bgpRsBestPathCtrlPol.attributes.tnBgpBestPathCtrlPolName == "ansible_bgp_best_path_policy"
+ - nm_add_bgp_protocol_profile.current.0.bgpProtP.children.1.bgpRsBgpNodeCtxPol.attributes.tnBgpCtxPolName == "ansible_bgp_timers_policy"
+ - nm_add_bgp_protocol_profile_idempotency is not changed
+ - nm_add_bgp_protocol_profile_2 is changed
+ - nm_add_bgp_protocol_profile_2.previous == []
+
+ - name: Query all BGP best path policies
+ aci_l3out_bgp_protocol_profile:
+ <<: *aci_info
+ state: query
+ register: query_all_bgp_protocol_profile
+
+ - name: Query ansible_bgp_protocol_profile_1
+ aci_l3out_bgp_protocol_profile:
+ <<: *aci_l3out_bgp_protocol_profile_present
+ state: query
+ register: query_ansible_bgp_protocol_profile_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_bgp_protocol_profile is not changed
+ - query_all_bgp_protocol_profile.current|length >= 2
+ - query_ansible_bgp_protocol_profile_1 is not changed
+ - query_ansible_bgp_protocol_profile_1.current.0.bgpProtP.children.0.bgpRsBestPathCtrlPol.attributes.tDn == "uni/tn-ansible_tenant/bestpath-ansible_bgp_best_path_policy"
+ - query_ansible_bgp_protocol_profile_1.current.0.bgpProtP.children.0.bgpRsBestPathCtrlPol.attributes.state == "formed"
+ - query_ansible_bgp_protocol_profile_1.current.0.bgpProtP.children.1.bgpRsBgpNodeCtxPol.attributes.tDn == "uni/tn-ansible_tenant/bgpCtxP-ansible_bgp_timers_policy"
+ - query_ansible_bgp_protocol_profile_1.current.0.bgpProtP.children.1.bgpRsBgpNodeCtxPol.attributes.state == "formed"
+
+ - name: Remove BGP protocol profile (check_mode)
+ aci_l3out_bgp_protocol_profile: &bgp_protocol_profile_absent
+ <<: *aci_l3out_bgp_protocol_profile_present
+ state: absent
+ check_mode: true
+ register: cm_remove_bgp_protocol_profile
+
+ - name: Remove BGP protocol profile (normal_mode)
+ aci_l3out_bgp_protocol_profile:
+ <<: *bgp_protocol_profile_absent
+ register: nm_remove_bgp_protocol_profile
+
+ - name: Remove BGP protocol profile - testing idempotency
+ aci_l3out_bgp_protocol_profile:
+ <<: *bgp_protocol_profile_absent
+ register: nm_remove_bgp_protocol_profile_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_bgp_protocol_profile is changed
+ - cm_remove_bgp_protocol_profile.proposed == {}
+ - nm_remove_bgp_protocol_profile is changed
+ - nm_remove_bgp_protocol_profile.previous != []
+ - nm_remove_bgp_protocol_profile.method == "DELETE"
+ - nm_remove_bgp_protocol_profile_idempotency is not changed
+ - nm_remove_bgp_protocol_profile_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml
new file mode 100644
index 000000000..d52fb5ef4
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg/tasks/main.yml
@@ -0,0 +1,364 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Akini Ross (akinross@cisco.com)
+
+# 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
+ 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: 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("info") }}'
+ aci_tenant: ansible_test
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when:
+ - query_cloud.current == []
+ block:
+
+ - name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+ # CLEAN TEST ENVIRONMENT
+
+ - name: Ensure clean tenant configuration
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ state: "{{ item }}"
+ loop:
+ - absent
+ - present
+
+ - name: Ensure clean vrf configuration
+ cisco.aci.aci_vrf:
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ vrf: vrf_1
+
+ - name: Ensure clean l3out configuration
+ cisco.aci.aci_l3out:
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ l3out: "{{ item }}"
+ vrf: vrf_1
+ domain: dom_1
+ loop:
+ - l3out_1
+ - l3out_2
+
+ # TEST CREATE L3OUT EXTERNAL EPG
+
+ - name: Add l3out external epg 1 ( check mode )
+ cisco.aci.aci_l3out_extepg: &add_l3out_extepg_1
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ l3out: l3out_1
+ extepg: extepg_1
+ state: present
+ check_mode: true
+ register: cm_add_l3out_extepg_1
+
+ - name: Add l3out external epg 1
+ cisco.aci.aci_l3out_extepg:
+ <<: *add_l3out_extepg_1
+ route_control_profiles:
+ import_profile: ""
+ register: nm_add_l3out_extepg_1
+
+ - name: Add l3out external epg 1 again
+ cisco.aci.aci_l3out_extepg:
+ <<: *add_l3out_extepg_1
+ register: nm_add_l3out_extepg_1_again
+
+ - name: Verify add l3out external epg 1
+ ansible.builtin.assert:
+ that:
+ - cm_add_l3out_extepg_1 is changed
+ - cm_add_l3out_extepg_1.current == []
+ - cm_add_l3out_extepg_1.previous == []
+ - cm_add_l3out_extepg_1.proposed.l3extInstP.attributes.name == "extepg_1"
+ - nm_add_l3out_extepg_1 is changed
+ - nm_add_l3out_extepg_1.previous == []
+ - nm_add_l3out_extepg_1.current.0.l3extInstP.attributes.name == "extepg_1"
+ - nm_add_l3out_extepg_1.current.0.l3extInstP.attributes.descr == ""
+ - nm_add_l3out_extepg_1.current.0.l3extInstP.attributes.prefGrMemb == "exclude"
+ - nm_add_l3out_extepg_1.current.0.l3extInstP.attributes.targetDscp == "unspecified"
+ - nm_add_l3out_extepg_1_again is not changed
+ - nm_add_l3out_extepg_1_again.previous.0.l3extInstP.attributes.name == "extepg_1"
+ - nm_add_l3out_extepg_1_again.previous.0.l3extInstP.attributes.descr == ""
+ - nm_add_l3out_extepg_1_again.previous.0.l3extInstP.attributes.prefGrMemb == "exclude"
+ - nm_add_l3out_extepg_1_again.previous.0.l3extInstP.attributes.targetDscp == "unspecified"
+ - nm_add_l3out_extepg_1_again.current.0.l3extInstP.attributes.name == "extepg_1"
+ - nm_add_l3out_extepg_1_again.current.0.l3extInstP.attributes.descr == ""
+ - nm_add_l3out_extepg_1_again.current.0.l3extInstP.attributes.prefGrMemb == "exclude"
+ - nm_add_l3out_extepg_1_again.current.0.l3extInstP.attributes.targetDscp == "unspecified"
+
+ - name: Change l3out external epg 1
+ cisco.aci.aci_l3out_extepg:
+ <<: *add_l3out_extepg_1
+ description: "changed description"
+ preferred_group: true
+ dscp: AF12
+ register: nm_change_l3out_extepg_1
+
+ - name: Verify change l3out external epg 1
+ ansible.builtin.assert:
+ that:
+ - nm_change_l3out_extepg_1 is changed
+ - nm_change_l3out_extepg_1.previous.0.l3extInstP.attributes.name == "extepg_1"
+ - nm_change_l3out_extepg_1.previous.0.l3extInstP.attributes.descr == ""
+ - nm_change_l3out_extepg_1.previous.0.l3extInstP.attributes.prefGrMemb == "exclude"
+ - nm_change_l3out_extepg_1.previous.0.l3extInstP.attributes.targetDscp == "unspecified"
+ - nm_change_l3out_extepg_1.current.0.l3extInstP.attributes.name == "extepg_1"
+ - nm_change_l3out_extepg_1.current.0.l3extInstP.attributes.descr == "changed description"
+ - nm_change_l3out_extepg_1.current.0.l3extInstP.attributes.prefGrMemb == "include"
+ - nm_change_l3out_extepg_1.current.0.l3extInstP.attributes.targetDscp == "AF12"
+
+ - name: Add two more l3out external epgs
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: "{{ aci_tenant }}"
+ l3out: "{{ item.l3out }}"
+ extepg: "{{ item.extepg }}"
+ state: present
+ loop:
+ - {l3out: l3out_1, extepg: extepg_2}
+ - {l3out: l3out_2, extepg: extepg_3}
+
+ - name: Add l3out external epg with the new optional params
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_params
+ contract_exception_tag: contract_excepted
+ qos_class: level6
+ route_control_profiles:
+ import_profile: profile1
+ export_profile: profile2
+ state: present
+ register: nm_l3out_extepg_optional_params
+
+ - name: Add l3out external epg with the new optional params again
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_params
+ contract_exception_tag: contract_excepted
+ qos_class: level6
+ route_control_profiles:
+ import_profile: profile1
+ export_profile: profile2
+ state: present
+ register: nm_l3out_extepg_optional_params_again
+
+ - name: Add l3out external epg with no export route control profile in the task
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_params
+ contract_exception_tag: contract_excepted
+ qos_class: level6
+ route_control_profiles:
+ import_profile: profile1
+ state: present
+ register: nm_l3out_extepg_non_existent_export_profile
+
+ - name: Add l3out external epg with export route control profile having ""
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_params
+ contract_exception_tag: contract_excepted
+ qos_class: level6
+ route_control_profiles:
+ import_profile: profile1
+ export_profile: ""
+ state: present
+ register: nm_l3out_extepg_remove_export_profile
+
+ - name: Add l3out external epg with export route control profile again
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_params
+ contract_exception_tag: contract_excepted
+ qos_class: level6
+ route_control_profiles:
+ import_profile: profile1
+ export: profile2
+ state: present
+ register: nm_l3out_extepg_add_export_profile
+
+ - name: Add l3out external epg with intra_ext_epg_isolation
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_isolation
+ intra_ext_epg_isolation: enforced
+ state: present
+ register: nm_l3out_extepg_isolation
+ when:
+ - version.current.0.topSystem.attributes.version is version('5.0', '>=')
+
+ # TEST QUERY L3OUT EXTERNAL EPG
+
+ - name: Query l3out external epg 1
+ cisco.aci.aci_l3out_extepg:
+ <<: *add_l3out_extepg_1
+ state: query
+ register: query_one
+
+ - name: Query all l3out external epgs ( class query )
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify query l3out external epgs
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.l3extInstP.attributes.name == "extepg_1"
+ - query_all is not changed
+ - query_all.current | length >= 3
+
+ - name: Query l3out external epg with the new optional params
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_params
+ state: query
+ register: query_l3out_extepg_optional_params
+
+ - name: Query l3out external epg with intra_ext_epg_isolation
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_isolation
+ state: query
+ register: query_l3out_extepg_isolation
+ when:
+ - version.current.0.topSystem.attributes.version is version('5.0', '>=')
+
+ - name: Gather attribute search results using regex
+ ansible.builtin.set_fact:
+ profile1_name: "{{ nm_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('profile1') }}"
+ profile1_direction: "{{ nm_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('import') }}"
+ profile2_name: "{{ nm_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('profile2') }}"
+ profile2_direction: "{{ nm_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('export') }}"
+ profile2_exists: "{{ nm_l3out_extepg_non_existent_export_profile.current.0.l3extInstP.children | regex_search('profile2') }}"
+ profile2_removed: "{{ nm_l3out_extepg_remove_export_profile.current.0.l3extInstP.children | regex_search('profile2') }}"
+ profile2_direction_removed: "{{ nm_l3out_extepg_remove_export_profile.current.0.l3extInstP.children | regex_search('export') }}"
+ query_profile1_name: "{{ query_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('profile1') }}"
+ query_profile1_direction: "{{ query_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('import') }}"
+ query_profile2_name: "{{ query_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('profile2') }}"
+ query_profile2_direction: "{{ query_l3out_extepg_optional_params.current.0.l3extInstP.children | regex_search('export') }}"
+
+ - name: Verify l3out external epg with the new optional params
+ ansible.builtin.assert:
+ that:
+ - nm_l3out_extepg_optional_params is changed
+ - nm_l3out_extepg_optional_params_again is not changed
+ - nm_l3out_extepg_non_existent_export_profile is not changed
+ - nm_l3out_extepg_remove_export_profile is changed
+ - nm_l3out_extepg_add_export_profile is changed
+ - query_l3out_extepg_optional_params is not changed
+ - nm_l3out_extepg_optional_params.current.0.l3extInstP.attributes.name == "extepg_params"
+ - nm_l3out_extepg_optional_params.current.0.l3extInstP.attributes.prio == "level6"
+ - profile1_name == "profile1"
+ - profile1_direction == "import"
+ - profile2_name == "profile2"
+ - profile2_direction == "export"
+ - query_profile1_name == "profile1"
+ - query_profile1_direction == "import"
+ - query_profile2_name == "profile2"
+ - query_profile2_direction == "export"
+ - profile2_exists == "profile2"
+ - profile2_removed == ""
+ - profile2_direction_removed == ""
+
+ - name: Verify l3out external epg with intra_ext_epg_isolation
+ ansible.builtin.assert:
+ that:
+ - nm_l3out_extepg_isolation.current.0.l3extInstP.attributes.pcEnfPref == "enforced"
+ - query_l3out_extepg_isolation.current.0.l3extInstP.attributes.pcEnfPref == "enforced"
+ when:
+ - version.current.0.topSystem.attributes.version is version('5.0', '>=')
+
+ # TEST REMOVAL L3OUT EXTERNAL EPG
+
+ - name: Remove l3out external epg 1 ( check mode )
+ cisco.aci.aci_l3out_extepg: &remove_l3out_extepg_1
+ <<: *add_l3out_extepg_1
+ state: absent
+ check_mode: true
+ register: cm_remove_l3out_extepg_1
+
+ - name: Remove l3out external epg 1
+ cisco.aci.aci_l3out_extepg:
+ <<: *remove_l3out_extepg_1
+ register: nm_remove_l3out_extepg_1
+
+ - name: Remove l3out external epg 1 again
+ cisco.aci.aci_l3out_extepg:
+ <<: *remove_l3out_extepg_1
+ register: nm_remove_l3out_extepg_1_again
+
+ - name: Remove l3out external epg params
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_params
+ state: absent
+ register: remove_l3out_extepg_params
+
+ - name: Remove l3out external epg with intra_ext_epg_isolation
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: l3out_1
+ extepg: extepg_isolation
+ state: absent
+ register: remove_l3out_extepg_isolation
+
+ - name: Verify removal epg monitoring policies
+ ansible.builtin.assert:
+ that:
+ - cm_remove_l3out_extepg_1 is changed
+ - cm_remove_l3out_extepg_1.proposed == {}
+ - nm_remove_l3out_extepg_1 is changed
+ - nm_remove_l3out_extepg_1.previous.0.l3extInstP.attributes.name == "extepg_1"
+ - nm_remove_l3out_extepg_1.current == []
+ - nm_remove_l3out_extepg_1_again is not changed
+ - nm_remove_l3out_extepg_1_again.previous == []
+ - nm_remove_l3out_extepg_1_again.current == []
+ - remove_l3out_extepg_params is changed
+ - remove_l3out_extepg_params.current == []
+ - remove_l3out_extepg_isolation.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml
index 4466369d5..b3ad827f1 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml
@@ -62,6 +62,7 @@
cisco.aci.aci_l3out_logical_interface_profile: &intf_present
<<: *np_present
interface_profile: INTFS
+ description: test
check_mode: true
register: cm_add_intf
@@ -77,6 +78,7 @@
- nm_add_intf is changed
- cm_add_intf.previous == nm_add_intf.previous == []
- cm_add_intf.sent.l3extLIfP.attributes.name == nm_add_intf.sent.l3extLIfP.attributes.name == 'INTFS'
+ - cm_add_intf.sent.l3extLIfP.attributes.descr == nm_add_intf.sent.l3extLIfP.attributes.descr == 'test'
- nm_add_intf.current.0.l3extLIfP.attributes.annotation == 'orchestrator:ansible'
- name: Add profile again, check if idempotency works
@@ -94,11 +96,13 @@
cisco.aci.aci_l3out_logical_interface_profile: &intf_update
<<: *intf_present
nd_policy: NDTEST
+ description: new test
register: update_intf
- name: Verify update_intf
assert:
that:
+ - update_intf.sent.l3extLIfP.attributes.descr == 'new test'
- update_intf is changed
- update_intf.previous != []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml
index 68bc64b20..1d61ee3e3 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml
@@ -1,6 +1,11 @@
# Author: Marcel Zehnder (@maercu)
# 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
+
# SET VARS
- name: Set vars
set_fact:
@@ -79,9 +84,9 @@
- cm_add_node is changed
- nm_add_node is changed
- cm_add_node.previous == nm_add_node.previous == []
- - cm_add_node.sent.l3extRsNodeL3OutAtt.attributes.rtrId == nm_add_node.sent.l3extRsNodeL3OutAtt.attributes.rtrId == '111.111.111.111'
- - cm_add_node.sent.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == nm_add_node.sent.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == 'no'
- - cm_add_node.sent.l3extRsNodeL3OutAtt.attributes.tDn == nm_add_node.sent.l3extRsNodeL3OutAtt.attributes.tDn == 'topology/pod-1/node-111'
+ - cm_add_node.sent.l3extRsNodeL3OutAtt.attributes.rtrId == nm_add_node.current.0.l3extRsNodeL3OutAtt.attributes.rtrId == '111.111.111.111'
+ - cm_add_node.sent.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == nm_add_node.current.0.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == 'no'
+ - cm_add_node.sent.l3extRsNodeL3OutAtt.attributes.tDn == nm_add_node.current.0.l3extRsNodeL3OutAtt.attributes.tDn == 'topology/pod-1/node-111'
- nm_add_node.current.0.l3extRsNodeL3OutAtt.attributes.annotation == 'orchestrator:ansible'
- name: Add node again, check if idempotency works
@@ -101,19 +106,37 @@
router_id: 11.11.11.11
register: update_node
+ - name: Add loopback address
+ cisco.aci.aci_l3out_logical_node: &node_add_loopback
+ <<: *node_update
+ loopback_address: 11.11.11.12
+ register: add_loopback_ip
+
+ - name: Remove loopback address
+ cisco.aci.aci_l3out_logical_node: &node_remove_loopback
+ <<: *node_add_loopback
+ loopback_address: ""
+ register: remove_loopback_ip
+
- name: Verify update_node
assert:
that:
- update_node is changed
- update_node.previous != []
- - update_node.sent.l3extRsNodeL3OutAtt.attributes.rtrId == '11.11.11.11'
+ - update_node.current.0.l3extRsNodeL3OutAtt.attributes.rtrId == '11.11.11.11'
+ - add_loopback_ip is changed
+ - add_loopback_ip.previous != []
+ - add_loopback_ip.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == '11.11.11.12'
+ - remove_loopback_ip is changed
+ - remove_loopback_ip.previous != []
# ADD ANOTHER NODE
- name: Add another node
- cisco.aci.aci_l3out_logical_node:
+ cisco.aci.aci_l3out_logical_node: &second_node_present
<<: *node_present
node_id: 112
router_id: 12.12.12.12
+ loopback_address: 12.12.12.13
# QUERY ALL NODES
- name: Query all nodes
@@ -131,7 +154,7 @@
# QUERY A SPECIFIC NODE
- name: Query a specific node
cisco.aci.aci_l3out_logical_node:
- <<: *node_update
+ <<: *second_node_present
state: query
register: query_spec_node
@@ -140,11 +163,13 @@
that:
- query_spec_node is not changed
- query_spec_node.current|length == 1
+ - query_spec_node.current.0.l3extRsNodeL3OutAtt.attributes.rtrId == '12.12.12.12'
+ - query_spec_node.current.0.l3extRsNodeL3OutAtt.children.0.l3extLoopBackIfP.attributes.addr == '12.12.12.13'
# REMOVE NODE
- name: Remove node
cisco.aci.aci_l3out_logical_node:
- <<: *node_update
+ <<: *node_remove_loopback
state: absent
register: remove_node
@@ -153,3 +178,9 @@
that:
- remove_node is changed
- remove_node.current == []
+
+ - name: Remove test tenant - clean-up the environment
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml
new file mode 100644
index 000000000..d7ad61c6d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_route_tag_policy/tasks/main.yml
@@ -0,0 +1,149 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: info
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Create tenant for tests
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ state: present
+ tenant: ansible_tenant
+
+ - name: Create first l3out route tag policy (check_mode)
+ cisco.aci.aci_l3out_route_tag_policy: &aci_rtp_present
+ <<: *aci_tenant_present
+ rtp: anstest
+ description: rtp test
+ tag: 1000
+ state: present
+ check_mode: true
+ register: cm_add_rtp
+
+ - name: Create first l3out route tag policy (normal_mode)
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_rtp_present
+ register: nm_add_rtp
+
+ - name: Create first l3out route tag policy again - testing idempotency
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_rtp_present
+ register: add_rtp_idempotency
+
+ - name: Create second l3out route tag policy
+ cisco.aci.aci_l3out_route_tag_policy: &aci_rtp_present_2
+ <<: *aci_tenant_present
+ rtp: anstest_2
+ state: present
+ register: nm_add_rtp_2
+
+ - name: asserts for creation tasks
+ assert:
+ that:
+ - cm_add_rtp is changed
+ - cm_add_rtp.previous == []
+ - cm_add_rtp.current == []
+ - nm_add_rtp is changed
+ - nm_add_rtp.current.0.l3extRouteTagPol.attributes.name == "anstest"
+ - nm_add_rtp.current.0.l3extRouteTagPol.attributes.descr == "rtp test"
+ - nm_add_rtp.current.0.l3extRouteTagPol.attributes.tag == "1000"
+ - add_rtp_idempotency is not changed
+ - nm_add_rtp_2 is changed
+ - nm_add_rtp_2.current.0.l3extRouteTagPol.attributes.name == "anstest_2"
+ - nm_add_rtp_2.current.0.l3extRouteTagPol.attributes.tag == "4294967295"
+
+ - name: Query all l3out route tag policies
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_tenant_present
+ state: query
+ register: query_all_rtp
+
+ - name: Query first l3out route tag policy
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_rtp_present
+ state: query
+ register: query_first_rtp
+
+ - name: asserts query tasks
+ assert:
+ that:
+ - query_all_rtp is not changed
+ - query_all_rtp.current.0.fvTenant.children | length >= 2
+ - query_all_rtp.current.0.fvTenant.children.0.l3extRouteTagPol.attributes.name == "anstest_2"
+ - query_all_rtp.current.0.fvTenant.children.1.l3extRouteTagPol.attributes.name == "anstest"
+ - query_first_rtp is not changed
+ - query_first_rtp.current.0.l3extRouteTagPol.attributes.name == "anstest"
+ - query_first_rtp.current.0.l3extRouteTagPol.attributes.descr == "rtp test"
+ - query_first_rtp.current.0.l3extRouteTagPol.attributes.tag == "1000"
+
+ - name: Delete first l3out route tag policy (check_mode)
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_rtp_present
+ state: absent
+ check_mode: true
+ register: cm_delete_rtp
+
+ - name: Delete first l3out route tag policy (normal_mode)
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_rtp_present
+ state: absent
+ register: nm_delete_rtp
+
+ - name: Delete first l3out route tag policy agaim - testing idempotency
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_rtp_present
+ state: absent
+ register: delete_rtp_idempotency
+
+ - name: Delete second l3out route tag policy
+ cisco.aci.aci_l3out_route_tag_policy:
+ <<: *aci_rtp_present_2
+ state: absent
+ register: nm_delete_rtp_2
+
+ - name: asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_rtp is changed
+ - cm_delete_rtp.proposed == {}
+ - nm_delete_rtp is changed
+ - nm_delete_rtp.previous != []
+ - nm_delete_rtp.current == []
+ - delete_rtp_idempotency is not changed
+ - delete_rtp_idempotency.previous == []
+ - nm_delete_rtp_2 is changed
+ - nm_delete_rtp_2.previous != []
+ - nm_delete_rtp_2.current == []
+
+ - name: Remove ansible_tenant - cleanup before ending tests
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml
new file mode 100644
index 000000000..12284c8a6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group/tasks/main.yml
@@ -0,0 +1,175 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Create Scheduler
+ aci_fabric_scheduler: &aci_fabric_scheduler_present
+ <<: *aci_info
+ name: anstest_scheduler
+ state: present
+
+ - name: Create maintenance policy
+ aci_maintenance_policy: &aci_maintenance_policy_present
+ <<: *aci_info
+ name: anstest_policy
+ scheduler: anstest_scheduler
+ state: present
+
+ - name: Ensure first maintenance group does not exist
+ aci_maintenance_group: &aci_maintenance_group_absent
+ <<: *aci_info
+ group: anstest_group
+ policy: anstest_policy
+ firmware_nodes_type: controller
+ type_group: all
+ description: test for maintenance group
+ state: absent
+
+ - name: Ensure second maintenance group does not exist
+ aci_maintenance_group: &aci_maintenance_group_2_absent
+ <<: *aci_info
+ group: anstest_group_2
+ policy: anstest_policy_2
+ state: absent
+
+ - name: Create first maintenance group (check_mode)
+ aci_maintenance_group: &aci_maintenance_group_present
+ <<: *aci_maintenance_group_absent
+ state: present
+ check_mode: true
+ register: cm_add_maintenance_group_1
+
+ - name: Create first maintenance group (normal_mode)
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_present
+ register: nm_add_maintenance_group_1
+
+ - name: Create first maintenance group again - testing idempotency
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_present
+ register: idempotency_add_maintenance_group_1
+
+ - name: Create second maintenance group
+ aci_maintenance_group: &aci_maintenance_group_2_present
+ <<: *aci_maintenance_group_2_absent
+ state: present
+ register: nm_add_maintenance_group_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_maintenance_group_1 is changed
+ - cm_add_maintenance_group_1.previous == []
+ - cm_add_maintenance_group_1.current == []
+ - nm_add_maintenance_group_1 is changed
+ - nm_add_maintenance_group_1.current.0.maintMaintGrp.attributes.name == "anstest_group"
+ - nm_add_maintenance_group_1.current.0.maintMaintGrp.attributes.fwtype == "controller"
+ - nm_add_maintenance_group_1.current.0.maintMaintGrp.attributes.type == "ALL"
+ - nm_add_maintenance_group_1.current.0.maintMaintGrp.children.0.maintRsMgrpp.attributes.tnMaintMaintPName == "anstest_policy"
+ - idempotency_add_maintenance_group_1 is not changed
+ - nm_add_maintenance_group_2 is changed
+ - nm_add_maintenance_group_2.current.0.maintMaintGrp.attributes.name == "anstest_group_2"
+ - nm_add_maintenance_group_2.current.0.maintMaintGrp.children.0.maintRsMgrpp.attributes.tnMaintMaintPName == "anstest_policy_2"
+ - nm_add_maintenance_group_2.current.0.maintMaintGrp.attributes.fwtype == "switch"
+ - nm_add_maintenance_group_2.current.0.maintMaintGrp.attributes.type == "range"
+
+
+ - name: Query all maintenance groups
+ aci_maintenance_group:
+ <<: *aci_info
+ state: query
+ register: query_all_maintenance_group
+
+ - name: Query first maintenance group
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_present
+ state: query
+ register: query_first_maintenance_group
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_maintenance_group is not changed
+ - query_all_maintenance_group.current | length >= 2
+ - '"maintRsMgrpp" in query_all_maintenance_group.filter_string'
+ - '"class/maintMaintGrp.json" in query_all_maintenance_group.url'
+ - query_all_maintenance_group.current.0.maintMaintGrp.attributes.name == "anstest_group"
+ - query_all_maintenance_group.current.1.maintMaintGrp.attributes.name == "anstest_group_2"
+ - query_first_maintenance_group is not changed
+ - query_first_maintenance_group.current.0.maintMaintGrp.attributes.name == "anstest_group"
+ - query_first_maintenance_group.current.0.maintMaintGrp.children.0.maintRsMgrpp.attributes.tnMaintMaintPName == "anstest_policy"
+ - query_first_maintenance_group.current.0.maintMaintGrp.attributes.fwtype == "controller"
+ - query_first_maintenance_group.current.0.maintMaintGrp.attributes.type == "ALL"
+
+ - name: Delete first maintenance group (check_mode)
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_present
+ state: absent
+ check_mode: true
+ register: cm_delete_maintenance_group_1
+
+ - name: Delete first maintenance group (normal_mode)
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_present
+ state: absent
+ register: nm_delete_maintenance_group_1
+
+ - name: Delete first maintenance group again - testing idempotency
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_present
+ state: absent
+ register: idempotency_delete_maintenance_group_1
+
+ - name: Delete second maintenance group (normal_mode)
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_2_present
+ state: absent
+ register: nm_delete_maintenance_group_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_maintenance_group_1 is changed
+ - cm_delete_maintenance_group_1.proposed == {}
+ - nm_delete_maintenance_group_1 is changed
+ - nm_delete_maintenance_group_1.previous != []
+ - nm_delete_maintenance_group_1.current == []
+ - idempotency_delete_maintenance_group_1 is not changed
+ - idempotency_delete_maintenance_group_1.previous == []
+ - nm_delete_maintenance_group_2 is changed
+ - nm_delete_maintenance_group_2.previous != []
+ - nm_delete_maintenance_group_2.current == []
+
+ - name: Delete maintenance policy - clean up the environment
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ state: absent
+
+ - name: Delete scheduler - clean up the environment
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml
new file mode 100644
index 000000000..9be9ecbe8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_group_node/tasks/main.yml
@@ -0,0 +1,174 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Create Scheduler
+ aci_fabric_scheduler: &aci_fabric_scheduler_present
+ <<: *aci_info
+ name: anstest_scheduler
+ state: present
+
+ - name: Create maintenance policy
+ aci_maintenance_policy: &aci_maintenance_policy_present
+ <<: *aci_info
+ name: anstest_policy
+ scheduler: anstest_scheduler
+ state: present
+
+ - name: Create maintenance groupe
+ aci_maintenance_group: &aci_maintenance_group_present
+ <<: *aci_info
+ group: anstest_group
+ policy: anstest_policy
+ state: present
+
+ - name: Ensure first maintenance group node does not exist
+ aci_maintenance_group_node: &aci_maintenance_group_node_absent
+ <<: *aci_info
+ group: anstest_group
+ node: 1001
+ state: absent
+
+ - name: Ensure second maintenance group node does not exist
+ aci_maintenance_group_node: &aci_maintenance_group_node_2_absent
+ <<: *aci_info
+ group: anstest_group
+ node: 1002
+ state: absent
+
+ - name: Create first maintenance group node (check_mode)
+ aci_maintenance_group_node: &aci_maintenance_group_node_present
+ <<: *aci_maintenance_group_node_absent
+ state: present
+ check_mode: true
+ register: cm_add_maintenance_group_node_1
+
+ - name: Create first maintenance group node (normal_mode)
+ aci_maintenance_group_node:
+ <<: *aci_maintenance_group_node_present
+ register: nm_add_maintenance_group_node_1
+
+ - name: Create first maintenance group node again - testing idempotency
+ aci_maintenance_group_node:
+ <<: *aci_maintenance_group_node_present
+ register: idempotency_add_maintenance_group_node_1
+
+ - name: Create second maintenance group node
+ aci_maintenance_group_node: &aci_maintenance_group_node_2_present
+ <<: *aci_maintenance_group_node_2_absent
+ state: present
+ register: nm_add_maintenance_group_node_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_maintenance_group_node_1 is changed
+ - cm_add_maintenance_group_node_1.previous == []
+ - cm_add_maintenance_group_node_1.current == []
+ - nm_add_maintenance_group_node_1 is changed
+ - nm_add_maintenance_group_node_1.current.0.fabricNodeBlk.attributes.from_ == "1001"
+ - nm_add_maintenance_group_node_1.current.0.fabricNodeBlk.attributes.to_ == "1001"
+ - idempotency_add_maintenance_group_node_1 is not changed
+ - nm_add_maintenance_group_node_2 is changed
+ - nm_add_maintenance_group_node_2.current.0.fabricNodeBlk.attributes.from_ == "1002"
+ - nm_add_maintenance_group_node_2.current.0.fabricNodeBlk.attributes.to_ == "1002"
+
+
+ - name: Query all maintenance group nodes
+ aci_maintenance_group_node:
+ <<: *aci_info
+ state: query
+ register: query_all_maintenance_group_node
+
+ - name: Query first maintenance group nnode
+ aci_maintenance_group_node:
+ <<: *aci_maintenance_group_node_present
+ state: query
+ register: query_first_maintenance_group_node
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_maintenance_group_node is not changed
+ - query_all_maintenance_group_node.current | length >= 2
+ - query_first_maintenance_group_node is not changed
+ - query_first_maintenance_group_node.current.0.fabricNodeBlk.attributes.from_ == "1001"
+ - query_first_maintenance_group_node.current.0.fabricNodeBlk.attributes.to_ == "1001"
+
+ - name: Delete first maintenance group (check_mode)
+ aci_maintenance_group_node:
+ <<: *aci_maintenance_group_node_present
+ state: absent
+ check_mode: true
+ register: cm_delete_maintenance_group_node_1
+
+ - name: Delete first maintenance group (normal_mode)
+ aci_maintenance_group_node:
+ <<: *aci_maintenance_group_node_present
+ state: absent
+ register: nm_delete_maintenance_group_node_1
+
+ - name: Delete first maintenance group again - testing idempotency
+ aci_maintenance_group_node:
+ <<: *aci_maintenance_group_node_present
+ state: absent
+ register: idempotency_delete_maintenance_group_1
+
+ - name: Delete second maintenance group (normal_mode)
+ aci_maintenance_group_node:
+ <<: *aci_maintenance_group_node_2_present
+ state: absent
+ register: nm_delete_maintenance_group_node_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_maintenance_group_node_1 is changed
+ - cm_delete_maintenance_group_node_1.proposed == {}
+ - nm_delete_maintenance_group_node_1 is changed
+ - nm_delete_maintenance_group_node_1.previous != []
+ - nm_delete_maintenance_group_node_1.current == []
+ - idempotency_delete_maintenance_group_1 is not changed
+ - idempotency_delete_maintenance_group_1.previous == []
+ - nm_delete_maintenance_group_node_2 is changed
+ - nm_delete_maintenance_group_node_2.previous != []
+ - nm_delete_maintenance_group_node_2.current == []
+
+ - name: Delete maintenance group - clean up the environment
+ aci_maintenance_group:
+ <<: *aci_maintenance_group_present
+ state: absent
+
+ - name: Delete maintenance policy - clean up the environment
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ state: absent
+
+ - name: Delete scheduler - clean up the environment
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml
new file mode 100644
index 000000000..8628c2a84
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_maintenance_policy/tasks/main.yml
@@ -0,0 +1,184 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: Create Scheduler
+ aci_fabric_scheduler: &aci_fabric_scheduler_present
+ <<: *aci_info
+ name: anstest_scheduler
+ state: present
+
+ - name: Ensure first maintenance policy does not exist
+ aci_maintenance_policy: &aci_maintenance_policy_absent
+ <<: *aci_info
+ name: anstest_policy
+ description: test for maintenance policy
+ run_mode: pause_never
+ graceful: True
+ scheduler: anstest_scheduler
+ ignore_compat: true
+ admin_state: untriggered
+ download_state: untriggered
+ notify_condition: notify_always_between_sets
+ smu_operation: smu_install
+ smu_operation_flags: smu_reload_skip
+ state: absent
+
+ - name: Ensure second maintenance policy does not exist
+ aci_maintenance_policy: &aci_maintenance_policy_2_absent
+ <<: *aci_info
+ name: anstest_policy_2
+ scheduler: anstest_scheduler
+ state: absent
+
+ - name: Create first maintenance policy (check_mode)
+ aci_maintenance_policy: &aci_maintenance_policy_present
+ <<: *aci_maintenance_policy_absent
+ state: present
+ check_mode: true
+ register: cm_add_maintenance_policy_1
+
+ - name: Create first maintenance policy (normal_mode)
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ register: nm_add_maintenance_policy_1
+
+ - name: Create first maintenance policy again - testing idempotency
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ register: idempotency_add_maintenance_policy_1
+
+ - name: Create second maintenance policy
+ aci_maintenance_policy: &aci_maintenance_policy_2_present
+ <<: *aci_maintenance_policy_2_absent
+ state: present
+ register: nm_add_maintenance_policy_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_maintenance_policy_1 is changed
+ - cm_add_maintenance_policy_1.previous == []
+ - cm_add_maintenance_policy_1.current == []
+ - nm_add_maintenance_policy_1 is changed
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.adminSt == "untriggered"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.downloadSt == "untriggered"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.notifCond == "notifyAlwaysBetweenSets"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.smuOperation == "smuInstall"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.smuOperationFlags == "smuReloadSkip"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.graceful == "yes"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.ignoreCompat == "yes"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.name == "anstest_policy"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.attributes.runMode == "pauseNever"
+ - nm_add_maintenance_policy_1.current.0.maintMaintP.children.0.maintRsPolScheduler.attributes.tnTrigSchedPName == "anstest_scheduler"
+ - idempotency_add_maintenance_policy_1 is not changed
+ - nm_add_maintenance_policy_2 is changed
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.adminSt == "untriggered"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.graceful == "no"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.ignoreCompat == "no"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.downloadSt == "untriggered"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.notifCond == "notifyOnlyOnFailures"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.smuOperation == "smuInstall"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.smuOperationFlags == "smuReloadImmediate"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.name == "anstest_policy_2"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.attributes.runMode == "pauseOnlyOnFailures"
+ - nm_add_maintenance_policy_2.current.0.maintMaintP.children.0.maintRsPolScheduler.attributes.tnTrigSchedPName == "anstest_scheduler"
+
+ - name: Query all maintenance policies
+ aci_maintenance_policy:
+ <<: *aci_info
+ state: query
+ register: query_all_maintenance_policy
+
+ - name: Query first maintenance policy
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ state: query
+ register: query_first_maintenance_policy
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_maintenance_policy is not changed
+ - query_all_maintenance_policy.current | length >= 2
+ - '"maintRsPolScheduler" in query_all_maintenance_policy.filter_string'
+ - '"class/maintMaintP.json" in query_all_maintenance_policy.url'
+ - query_first_maintenance_policy is not changed
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.adminSt == "untriggered"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.downloadSt == "untriggered"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.notifCond == "notifyAlwaysBetweenSets"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.smuOperation == "smuInstall"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.smuOperationFlags == "smuReloadSkip"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.graceful == "yes"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.ignoreCompat == "yes"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.name == "anstest_policy"
+ - query_first_maintenance_policy.current.0.maintMaintP.attributes.runMode == "pauseNever"
+ - query_first_maintenance_policy.current.0.maintMaintP.children.0.maintRsPolScheduler.attributes.tnTrigSchedPName == "anstest_scheduler"
+
+ - name: Delete first maintenance policy (check_mode)
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ state: absent
+ check_mode: true
+ register: cm_delete_maintenance_policy_1
+
+ - name: Delete first maintenance policy (normal_mode)
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ state: absent
+ register: nm_delete_maintenance_policy_1
+
+ - name: Delete first maintenance policy again - testing idempotency
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_present
+ state: absent
+ register: idempotency_delete_maintenance_policy_1
+
+ - name: Delete second maintenance policy (normal_mode)
+ aci_maintenance_policy:
+ <<: *aci_maintenance_policy_2_present
+ state: absent
+ register: nm_delete_maintenance_policy_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_maintenance_policy_1 is changed
+ - cm_delete_maintenance_policy_1.proposed == {}
+ - nm_delete_maintenance_policy_1 is changed
+ - nm_delete_maintenance_policy_1.previous != []
+ - nm_delete_maintenance_policy_1.current == []
+ - idempotency_delete_maintenance_policy_1 is not changed
+ - idempotency_delete_maintenance_policy_1.previous == []
+ - nm_delete_maintenance_policy_2 is changed
+ - nm_delete_maintenance_policy_2.previous != []
+ - nm_delete_maintenance_policy_2.current == []
+
+ - name: Delete scheduler - clean up the environment
+ aci_fabric_scheduler:
+ <<: *aci_fabric_scheduler_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml
new file mode 100644
index 000000000..cdabd8b4e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml
@@ -0,0 +1,150 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a match rule profile
+ aci_match_rule:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: match rule profile for ansible_tenant tenant
+ state: present
+ register: cm_add_match_rule
+
+ - name: Add a match regex AS-Path term (check_mode)
+ aci_match_as_path_regex_term: &aci_match_as_path_regex_term_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ match_as_path_regex_term: ansible_match_as_path_regex_term_1
+ description: match regex AS-Path term 1 for ansible_match_rule match rule profile
+ regex: .*
+ state: present
+ check_mode: true
+ register: cm_add_match_as_path_regex_term
+
+ - name: Add a match regex AS-Path term (normal_mode)
+ aci_match_as_path_regex_term:
+ <<: *aci_match_as_path_regex_term_present
+ register: nm_add_match_as_path_regex_term
+
+ - name: Add the first match regex AS-Path term again - testing idempotency
+ aci_match_as_path_regex_term:
+ <<: *aci_match_as_path_regex_term_present
+ register: nm_add_match_as_path_regex_term_idempotency
+
+ - name: Add a second match regex AS-Path term (normal_mode)
+ aci_match_as_path_regex_term:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ match_as_path_regex_term: ansible_match_as_path_regex_term_2
+ description: match regex AS-Path term 2 for ansible_match_rule match rule profile
+ state: present
+ register: nm_add_match_as_path_regex_term_2
+
+ - name: Asserts for match regex AS-Path terms creation tasks
+ assert:
+ that:
+ - cm_add_match_as_path_regex_term is changed
+ - cm_add_match_as_path_regex_term.previous == []
+ - cm_add_match_as_path_regex_term.current == []
+ - nm_add_match_as_path_regex_term is changed
+ - nm_add_match_as_path_regex_term.current.0.rtctrlMatchAsPathRegexTerm.attributes.name == "ansible_match_as_path_regex_term_1"
+ - nm_add_match_as_path_regex_term.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == ".*"
+ - nm_add_match_as_path_regex_term_idempotency is not changed
+ - nm_add_match_as_path_regex_term_2 is changed
+ - nm_add_match_as_path_regex_term_2.previous == []
+ - nm_add_match_as_path_regex_term_2.current.0.rtctrlMatchAsPathRegexTerm.attributes.name == "ansible_match_as_path_regex_term_2"
+ - nm_add_match_as_path_regex_term_2.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == ""
+
+ - name: Query all match regex AS-Path terms
+ aci_match_as_path_regex_term:
+ <<: *aci_info
+ state: query
+ register: query_all_match_as_path_regex_term
+
+ - name: Query ansible_match_as_path_regex_term_1
+ aci_match_as_path_regex_term:
+ <<: *aci_match_as_path_regex_term_present
+ state: query
+ register: query_ansible_match_as_path_regex_term_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_match_as_path_regex_term is not changed
+ - query_all_match_as_path_regex_term.current|length >= 2
+ - query_ansible_match_as_path_regex_term_1 is not changed
+ - query_ansible_match_as_path_regex_term_1.current.0.rtctrlMatchAsPathRegexTerm.attributes.name == "ansible_match_as_path_regex_term_1"
+ - query_ansible_match_as_path_regex_term_1.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == ".*"
+
+ - name: Remove match regex AS-Path term for l3out (check_mode)
+ aci_match_as_path_regex_term: &match_as_path_regex_term_absent
+ <<: *aci_match_as_path_regex_term_present
+ state: absent
+ check_mode: true
+ register: cm_remove_match_as_path_regex_term
+
+ - name: Remove match regex AS-Path term for l3out (normal_mode)
+ aci_match_as_path_regex_term:
+ <<: *match_as_path_regex_term_absent
+ register: nm_remove_match_as_path_regex_term
+
+ - name: Remove match regex AS-Path term for l3out again - testing previous Removal
+ aci_match_as_path_regex_term:
+ <<: *match_as_path_regex_term_absent
+ register: nm_remove_match_as_path_regex_term_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_match_as_path_regex_term is changed
+ - cm_remove_match_as_path_regex_term.proposed == {}
+ - nm_remove_match_as_path_regex_term is changed
+ - nm_remove_match_as_path_regex_term.previous != []
+ - nm_remove_match_as_path_regex_term.method == "DELETE"
+ - nm_remove_match_as_path_regex_term_idempotency is not changed
+ - nm_remove_match_as_path_regex_term_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml
new file mode 100644
index 000000000..2cc1f3ac1
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_factor/tasks/main.yml
@@ -0,0 +1,157 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a match rule profile
+ aci_match_rule:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: match rule profile for ansible_tenant tenant
+ state: present
+
+ - name: Add a match community term
+ aci_match_community_term:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ match_community_term: ansible_match_community_term
+ description: match community term for ansible_match_rule match rule profile
+ state: present
+
+ - name: Add a match community factor (check_mode)
+ aci_match_community_factor: &aci_match_community_factor_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ match_community_term: ansible_match_community_term
+ community: regular:as2-nn2:4:15
+ scope: non-transitive
+ description: match community factor 1 for ansible_match_community_term
+ state: present
+ check_mode: true
+ register: cm_add_match_community_factor
+
+ - name: Add a match community factor (normal_mode)
+ aci_match_community_factor:
+ <<: *aci_match_community_factor_present
+ register: nm_add_match_community_factor
+
+ - name: Add the first match community factor again - testing idempotency
+ aci_match_community_factor:
+ <<: *aci_match_community_factor_present
+ register: nm_add_match_community_factor_idempotency
+
+ - name: Add a second match community factor (normal_mode)
+ aci_match_community_factor:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ match_community_term: ansible_match_community_term
+ community: regular:as2-nn2:4:16
+ description: match community factor 2 for ansible_match_community_term
+ state: present
+ register: nm_add_match_community_factor_2
+
+ - name: Asserts for match community factors creation tasks
+ assert:
+ that:
+ - cm_add_match_community_factor is changed
+ - cm_add_match_community_factor.previous == []
+ - cm_add_match_community_factor.current == []
+ - nm_add_match_community_factor is changed
+ - nm_add_match_community_factor.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:15"
+ - nm_add_match_community_factor_idempotency is not changed
+ - nm_add_match_community_factor_2 is changed
+ - nm_add_match_community_factor_2.previous == []
+ - nm_add_match_community_factor_2.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:16"
+
+ - name: Query all match community factors
+ aci_match_community_factor:
+ <<: *aci_info
+ state: query
+ register: query_all_match_community_factor
+
+ - name: Query a specific match community factor
+ aci_match_community_factor:
+ <<: *aci_match_community_factor_present
+ state: query
+ register: query_ansible_match_community_factor_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_match_community_factor is not changed
+ - query_all_match_community_factor.current|length >= 2
+ - query_ansible_match_community_factor_1 is not changed
+ - query_ansible_match_community_factor_1.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:15"
+
+ - name: Remove match community factor (check_mode)
+ aci_match_community_factor: &match_community_term_absent
+ <<: *aci_match_community_factor_present
+ state: absent
+ check_mode: true
+ register: cm_remove_match_community_factor
+
+ - name: Remove match community factor (normal_mode)
+ aci_match_community_factor:
+ <<: *match_community_term_absent
+ register: nm_remove_match_community_factor
+
+ - name: Remove match community factor again - testing previous Removal
+ aci_match_community_factor:
+ <<: *match_community_term_absent
+ register: nm_remove_match_community_factor_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_match_community_factor is changed
+ - cm_remove_match_community_factor.proposed == {}
+ - nm_remove_match_community_factor is changed
+ - nm_remove_match_community_factor.previous != []
+ - nm_remove_match_community_factor.method == "DELETE"
+ - nm_remove_match_community_factor_idempotency is not changed
+ - nm_remove_match_community_factor_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml
new file mode 100644
index 000000000..c0b12c78c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml
@@ -0,0 +1,152 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a match rule profile
+ aci_match_rule:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: match rule profile for ansible_tenant tenant
+ state: present
+ register: cm_add_match_rule
+
+ - name: Add a match community regex term (check_mode)
+ aci_match_community_regex_term: &aci_match_community_regex_term_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ name: ansible_community_regex_extended
+ description: match extended community regex term for ansible_match_rule match rule profile
+ community_type: extended
+ regex: .*
+ state: present
+ check_mode: true
+ register: cm_add_match_community_regex_term
+
+ - name: Add a match community regex term (normal_mode)
+ aci_match_community_regex_term:
+ <<: *aci_match_community_regex_term_present
+ register: nm_add_match_community_regex_term
+
+ - name: Add the first match community regex term again - testing idempotency
+ aci_match_community_regex_term:
+ <<: *aci_match_community_regex_term_present
+ register: nm_add_match_community_regex_term_idempotency
+
+ - name: Add a second match community regex term (normal_mode)
+ aci_match_community_regex_term: &aci_match_community_regex_term_2_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: match regular community regex term for ansible_match_rule match rule profile
+ state: present
+ register: nm_add_match_community_regex_term_2
+
+ - name: Asserts for match community regex terms creation tasks
+ assert:
+ that:
+ - cm_add_match_community_regex_term is changed
+ - cm_add_match_community_regex_term.previous == []
+ - cm_add_match_community_regex_term.current == []
+ - nm_add_match_community_regex_term is changed
+ - nm_add_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.regex == ".*"
+ - nm_add_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.name == "ansible_community_regex_extended"
+ - nm_add_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "extended"
+ - nm_add_match_community_regex_term_idempotency is not changed
+ - nm_add_match_community_regex_term_2 is changed
+ - nm_add_match_community_regex_term_2.previous == []
+ - nm_add_match_community_regex_term_2.current.0.rtctrlMatchCommRegexTerm.attributes.regex == ""
+ - nm_add_match_community_regex_term_2.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "regular"
+
+ - name: Query all match community regex terms
+ aci_match_community_regex_term:
+ <<: *aci_info
+ state: query
+ community_type: extended
+ register: query_all_match_community_regex_term
+
+ - name: Query ansible_match_community_regex_term_regular
+ aci_match_community_regex_term:
+ <<: *aci_match_community_regex_term_2_present
+ state: query
+ register: query_ansible_match_community_regex_term_regular
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_match_community_regex_term is not changed
+ - query_all_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "extended"
+ - query_ansible_match_community_regex_term_regular is not changed
+ - query_ansible_match_community_regex_term_regular.current.0.rtctrlMatchCommRegexTerm.attributes.regex == ""
+ - query_ansible_match_community_regex_term_regular.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "regular"
+
+ - name: Remove match community regex term (check_mode)
+ aci_match_community_regex_term: &match_community_regex_term_absent
+ <<: *aci_match_community_regex_term_present
+ state: absent
+ check_mode: true
+ register: cm_remove_match_community_regex_term
+
+ - name: Remove match community regex term (normal_mode)
+ aci_match_community_regex_term:
+ <<: *match_community_regex_term_absent
+ register: nm_remove_match_community_regex_term
+
+ - name: Remove match community regex term again - testing previous Removal
+ aci_match_community_regex_term:
+ <<: *match_community_regex_term_absent
+ register: nm_remove_match_community_regex_term_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_match_community_regex_term is changed
+ - cm_remove_match_community_regex_term.proposed == {}
+ - nm_remove_match_community_regex_term is changed
+ - nm_remove_match_community_regex_term.previous != []
+ - nm_remove_match_community_regex_term.method == "DELETE"
+ - nm_remove_match_community_regex_term_idempotency is not changed
+ - nm_remove_match_community_regex_term_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml
new file mode 100644
index 000000000..aecf89096
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_community_term/tasks/main.yml
@@ -0,0 +1,146 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a match rule profile
+ aci_match_rule:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: match rule profile for ansible_tenant tenant
+ state: present
+ register: cm_add_match_rule
+
+ - name: Add a match community term (check_mode)
+ aci_match_community_term: &aci_match_community_term_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ match_community_term: ansible_match_community_term_1
+ description: match community term 1 for ansible_match_rule match rule profile
+ state: present
+ check_mode: true
+ register: cm_add_match_community_term
+
+ - name: Add a match community term (normal_mode)
+ aci_match_community_term:
+ <<: *aci_match_community_term_present
+ register: nm_add_match_community_term
+
+ - name: Add the first match community term again - testing idempotency
+ aci_match_community_term:
+ <<: *aci_match_community_term_present
+ register: nm_add_match_community_term_idempotency
+
+ - name: Add a second match community term (normal_mode)
+ aci_match_community_term:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ match_community_term: ansible_match_community_term_2
+ description: match community term 2 for ansible_match_rule match rule profile
+ state: present
+ register: nm_add_match_community_term_2
+
+ - name: Asserts for match community terms creation tasks
+ assert:
+ that:
+ - cm_add_match_community_term is changed
+ - cm_add_match_community_term.previous == []
+ - cm_add_match_community_term.current == []
+ - nm_add_match_community_term is changed
+ - nm_add_match_community_term.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_1"
+ - nm_add_match_community_term_idempotency is not changed
+ - nm_add_match_community_term_2 is changed
+ - nm_add_match_community_term_2.previous == []
+ - nm_add_match_community_term_2.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_2"
+
+ - name: Query all match community terms
+ aci_match_community_term:
+ <<: *aci_info
+ state: query
+ register: query_all_match_community_term
+
+ - name: Query ansible_match_community_term_1
+ aci_match_community_term:
+ <<: *aci_match_community_term_present
+ state: query
+ register: query_ansible_match_community_term_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_match_community_term is not changed
+ - query_all_match_community_term.current|length >= 2
+ - query_ansible_match_community_term_1 is not changed
+ - query_ansible_match_community_term_1.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_1"
+
+ - name: Remove match community term (check_mode)
+ aci_match_community_term: &match_community_term_absent
+ <<: *aci_match_community_term_present
+ state: absent
+ check_mode: true
+ register: cm_remove_match_community_term
+
+ - name: Remove match community term (normal_mode)
+ aci_match_community_term:
+ <<: *match_community_term_absent
+ register: nm_remove_match_community_term
+
+ - name: Remove match community term again - testing previous Removal
+ aci_match_community_term:
+ <<: *match_community_term_absent
+ register: nm_remove_match_community_term_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_match_community_term is changed
+ - cm_remove_match_community_term.proposed == {}
+ - nm_remove_match_community_term is changed
+ - nm_remove_match_community_term.previous != []
+ - nm_remove_match_community_term.method == "DELETE"
+ - nm_remove_match_community_term_idempotency is not changed
+ - nm_remove_match_community_term_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml
new file mode 100644
index 000000000..b4d49c2ff
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_route_destination/tasks/main.yml
@@ -0,0 +1,159 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+# Copyright: (c) 2023, Tim Cragg (@timcragg) <tcragg@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a match rule profile
+ aci_match_rule:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: subject profile for ansible_tenant tenant
+ state: present
+ register: cm_add_match_rule
+
+ - name: Add a match route destination rule (check_mode)
+ aci_match_route_destination: &aci_match_route_destination_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: match route destination rule 1 for ansible_match_rule match rule profile
+ ip: 11.11.11.11/24
+ aggregate: yes
+ from_prefix_length: 0
+ to_prefix_length: 32
+ state: present
+ check_mode: true
+ register: cm_add_match_route_destination
+
+ - name: Add a match route destination rule (normal_mode)
+ aci_match_route_destination:
+ <<: *aci_match_route_destination_present
+ register: nm_add_match_route_destination
+
+ - name: Add the first match route destination rule again - testing idempotency
+ aci_match_route_destination:
+ <<: *aci_match_route_destination_present
+ register: nm_add_match_route_destination_idempotency
+
+ - name: Add a second match route destination rule (normal_mode)
+ aci_match_route_destination:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: match route destination rule 2 for ansible_match_rule match rule profile
+ ip: 11.11.11.12/24
+ state: present
+ register: nm_add_match_route_destination_2
+
+ - name: Asserts for match route destination rule creation tasks
+ assert:
+ that:
+ - cm_add_match_route_destination is changed
+ - cm_add_match_route_destination.previous == []
+ - cm_add_match_route_destination.current == []
+ - nm_add_match_route_destination is changed
+ - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.ip == "11.11.11.11/24"
+ - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.aggregate == "yes"
+ - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.fromPfxLen == "0"
+ - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "32"
+ - nm_add_match_route_destination_idempotency is not changed
+ - nm_add_match_route_destination_2 is changed
+ - nm_add_match_route_destination_2.previous == []
+ - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.ip == "11.11.11.12/24"
+ - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.aggregate == "no"
+ - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.fromPfxLen == "0"
+ - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "0"
+
+ - name: Query all match regex AS-Path terms
+ aci_match_route_destination:
+ <<: *aci_info
+ state: query
+ register: query_all_match_route_destination
+
+ - name: Query ansible_match_route_destination_1
+ aci_match_route_destination:
+ <<: *aci_match_route_destination_present
+ state: query
+ register: query_ansible_match_route_destination_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_match_route_destination is not changed
+ - query_all_match_route_destination.current|length >= 2
+ - query_ansible_match_route_destination_1 is not changed
+ - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.ip == "11.11.11.11/24"
+ - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.aggregate == "yes"
+ - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.fromPfxLen == "0"
+ - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "32"
+
+ - name: Remove match route destination rule (check_mode)
+ aci_match_route_destination: &match_route_destination_absent
+ <<: *aci_match_route_destination_present
+ state: absent
+ check_mode: true
+ register: cm_remove_match_route_destination
+
+ - name: Remove match route destination rule (normal_mode)
+ aci_match_route_destination:
+ <<: *match_route_destination_absent
+ register: nm_remove_match_route_destination
+
+ - name: Remove match route destination rule again - testing previous Removal
+ aci_match_route_destination:
+ <<: *match_route_destination_absent
+ register: nm_remove_match_route_destination_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_match_route_destination is changed
+ - cm_remove_match_route_destination.proposed == {}
+ - nm_remove_match_route_destination is changed
+ - nm_remove_match_route_destination.previous != []
+ - nm_remove_match_route_destination.method == "DELETE"
+ - nm_remove_match_route_destination_idempotency is not changed
+ - nm_remove_match_route_destination_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml
new file mode 100644
index 000000000..23509494c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_match_rule/tasks/main.yml
@@ -0,0 +1,136 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+# Copyright: (c) 2023, Tim Cragg (@timcragg) <tcragg@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a match rule profile (check_mode)
+ aci_match_rule: &aci_match_rule_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule_1
+ description: match rule profile 1 for ansible_tenant tenant
+ state: present
+ check_mode: true
+ register: cm_add_match_rule
+
+ - name: Add a match rule profile (normal_mode)
+ aci_match_rule:
+ <<: *aci_match_rule_present
+ register: nm_add_match_rule
+
+ - name: Add the first match rule profile again - testing idempotency
+ aci_match_rule:
+ <<: *aci_match_rule_present
+ register: nm_add_match_rule_idempotency
+
+ - name: Add a second match rule profile (normal_mode)
+ aci_match_rule:
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule_2
+ description: match rule profile 2 for ansible_tenant tenant
+ state: present
+ register: nm_add_match_rule_2
+
+ - name: Asserts for match rule profiles creation tasks
+ assert:
+ that:
+ - cm_add_match_rule is changed
+ - cm_add_match_rule.previous == []
+ - cm_add_match_rule.current == []
+ - nm_add_match_rule is changed
+ - nm_add_match_rule.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_1"
+ - nm_add_match_rule_idempotency is not changed
+ - nm_add_match_rule_2 is changed
+ - nm_add_match_rule_2.previous == []
+ - nm_add_match_rule_2.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_2"
+
+ - name: Query all match rule profiles
+ aci_match_rule:
+ <<: *aci_info
+ state: query
+ register: query_all_match_rule
+
+ - name: Query ansible_match_rule_1
+ aci_match_rule:
+ <<: *aci_match_rule_present
+ state: query
+ register: query_ansible_match_rule_1
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_match_rule is not changed
+ - query_all_match_rule.current|length >= 2
+ - query_ansible_match_rule_1 is not changed
+ - query_ansible_match_rule_1.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_1"
+
+ - name: Remove match rule profile for l3out (check_mode)
+ aci_match_rule: &match_rule_absent
+ <<: *aci_match_rule_present
+ state: absent
+ check_mode: true
+ register: cm_remove_match_rule
+
+ - name: Remove match rule profile for l3out (normal_mode)
+ aci_match_rule:
+ <<: *match_rule_absent
+ register: nm_remove_match_rule
+
+ - name: Remove match rule profile for l3out again - testing previous Removal
+ aci_match_rule:
+ <<: *match_rule_absent
+ register: nm_remove_match_rule_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_match_rule is changed
+ - cm_remove_match_rule.proposed == {}
+ - nm_remove_match_rule is changed
+ - nm_remove_match_rule.previous != []
+ - nm_remove_match_rule.method == "DELETE"
+ - nm_remove_match_rule_idempotency is not changed
+ - nm_remove_match_rule_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml
index 1c503c5f2..49c6fca53 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml
@@ -27,11 +27,10 @@
assert:
that:
- error_on_name_resolution is failed
- - error_on_name_resolution.msg.startswith("Connection failed for https://foo.bar.cisco.com/api/aaaLogin.json. Request failed:")
+ - error_on_name_resolution.msg.startswith("Connection failed for https://foo.bar.cisco.com/api/aaaLogin.json.")
- "'current' not in error_on_name_resolution"
- "'previous' not in error_on_name_resolution"
- "'sent' not in error_on_name_resolution"
- - "'proposed' not in error_on_name_resolution"
- "'filter_string' not in error_on_name_resolution"
- name: Error when required parameter is missing
@@ -59,7 +58,6 @@
- "'current' not in error_on_missing_required_param"
- "'previous' not in error_on_missing_required_param"
- "'sent' not in error_on_missing_required_param"
- - "'proposed' not in error_on_missing_required_param"
- "'filter_string' not in error_on_missing_required_param"
- name: Error when attributes are missing
@@ -90,7 +88,6 @@
- "'current' not in error_on_missing_attributes"
- "'previous' not in error_on_missing_attributes"
- "'sent' not in error_on_missing_attributes"
- - "'proposed' not in error_on_missing_attributes"
- "'filter_string' not in error_on_missing_attributes"
- name: Error when input does not validate
@@ -123,7 +120,6 @@
- "'current' not in error_on_input_validation"
- "'previous' not in error_on_input_validation"
- "'sent' not in error_on_input_validation"
- - "'proposed' not in error_on_input_validation"
- "'filter_string' not in error_on_input_validation"
- name: Error when invalid attributes are used
@@ -156,7 +152,6 @@
- "'current' not in error_on_invalid_attributes"
- "'previous' not in error_on_invalid_attributes"
- "'sent' not in error_on_invalid_attributes"
- - "'proposed' not in error_on_invalid_attributes"
- "'filter_string' not in error_on_invalid_attributes"
- name: Error on invalid object
@@ -188,7 +183,6 @@
- "'current' not in error_on_invalid_object"
- "'previous' not in error_on_invalid_object"
- "'sent' not in error_on_invalid_object"
- - "'proposed' not in error_on_invalid_object"
# Test case for certificate based error issue: https://github.com/CiscoDevNet/ansible-aci/issues/339
# Original error was with ospfCtxPol but same behaviour detected for tenant creation thus simplifying the test case
@@ -227,4 +221,104 @@
cisco.aci.aci_rest:
<<: *tenant
content:
- <fvTenant name="test_tenant_cert_auth" status="deleted"/> \ No newline at end of file
+ <fvTenant name="test_tenant_cert_auth" status="deleted"/>
+
+# Test cases for import error handling
+
+- name: Uninstall lxml for error checking
+ ansible.builtin.pip: &lxml
+ name: lxml
+ state: absent
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+- name: Uninstall xmljson for error checking
+ ansible.builtin.pip: &xmljson
+ name: xmljson
+ state: absent
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+- name: Uninstall pyyaml for error checking
+ ansible.builtin.pip: &pyyaml
+ name: pyyaml
+ state: absent
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+ when: ansible_connection == "local"
+
+- name: Create tenant with invalid src attribute
+ cisco.aci.aci_rest:
+ <<: *tenant
+ ignore_errors: true
+ register: err_missing_lxml
+
+- name: Install lxml
+ ansible.builtin.pip:
+ <<: *lxml
+ state: present
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+- name: Create tenant with invalid src attribute
+ cisco.aci.aci_rest:
+ <<: *tenant
+ ignore_errors: true
+ register: err_missing_xmljson
+
+- name: Install xmljson
+ ansible.builtin.pip:
+ <<: *xmljson
+ state: present
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+
+- name: Install pyyaml
+ ansible.builtin.pip:
+ <<: *pyyaml
+ state: present
+ ignore_errors: true # ignore errors to because of multiple executions for hosts at the same time
+ when: ansible_connection == "local"
+
+# Test case for invalid src
+
+- name: Create tenant with invalid src attribute
+ cisco.aci.aci_rest:
+ <<: *tenant
+ src: "./targets/aci_rest/invalid_src.txt"
+ content: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: err_src_attribute
+
+# Test case for invalid path extension
+
+- name: Create tenant with invalid path extension
+ cisco.aci.aci_rest:
+ <<: *tenant
+ path: /api/mo/uni.invalid
+ ignore_errors: true
+ register: err_extension
+
+# Parse failures
+
+- name: Create tenant with fail to parse xml
+ cisco.aci.aci_rest:
+ <<: *tenant
+ src: "./targets/aci_rest/tasks/xml_files/fail_parse.xml"
+ content: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: err_fail_parse_xml
+
+- name: Create tenant with fail to parse json
+ cisco.aci.aci_rest:
+ <<: *tenant
+ path: /api/mo/uni.json
+ src: "./targets/aci_rest/tasks/xml_files/fail_parse.json"
+ content: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: err_fail_parse_json
+
+- name: Assertions checks for import error handling, invalid src, invalid path extension and parse failures
+ assert:
+ that:
+ - err_missing_lxml.msg == "The lxml python library is missing, or lacks etree support."
+ - err_missing_xmljson.msg == "The xmljson python library is missing, or lacks cobra support."
+ - err_src_attribute.msg == "Cannot find/access src './targets/aci_rest/invalid_src.txt'"
+ - err_extension.msg == "Failed to find REST API payload type (neither .xml nor .json)."
+ - err_fail_parse_xml.msg.startswith("Failed to parse provided XML payload")
+ - err_fail_parse_json.msg.startswith("Failed to parse provided JSON/YAML payload")
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml
index dd27525f9..3d5c9be48 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml
@@ -18,7 +18,7 @@
method: delete
# ADD TENANT
-- name: Add tenant (normal mode)
+- name: Add tenant (check mode)
cisco.aci.aci_rest: &tenant_present
host: '{{ aci_hostname }}'
username: '{{ aci_username }}'
@@ -37,12 +37,35 @@
}
}
}
- delegate_to: localhost
+ register: cm_add_tenant
+ check_mode: true
+
+- name: Verify checkmode did not create tenant
+ cisco.aci.aci_tenant:
+ 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: ansible_test
+ state: query
+ register: cm_verify_checkmode_tenant
+
+- name: Verify checkmode POST operation
+ assert:
+ that:
+ - cm_add_tenant is changed
+ - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test"
+ - cm_verify_checkmode_tenant.current == []
+
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_present
register: nm_add_tenant
- name: Add tenant again (normal mode)
cisco.aci.aci_rest: *tenant_present
- delegate_to: localhost
register: nm_add_tenant_again
- name: Verify add_tenant
@@ -72,12 +95,10 @@
}
}
}
- delegate_to: localhost
register: nm_add_tenant_descr
- name: Change description of tenant again (normal mode)
cisco.aci.aci_rest: *tenant_changed
- delegate_to: localhost
register: nm_add_tenant_descr_again
- name: Verify add_tenant_descr
@@ -89,7 +110,6 @@
# ADD TENANT AGAIN
- name: Add tenant again with no description (normal mode)
cisco.aci.aci_rest: *tenant_present
- delegate_to: localhost
register: nm_add_tenant_again_no_descr
- name: Verify add_tenant_again_no_descr
@@ -109,7 +129,6 @@
output_level: '{{ aci_output_level | default("info") }}'
path: /api/mo/uni/tn-[ansible_test].json
method: get
- delegate_to: localhost
register: nm_query_all_tenants
- name: Verify query_all_tenants
@@ -129,7 +148,6 @@
output_level: '{{ aci_output_level | default("info") }}'
path: /api/mo/uni/tn-[ansible_test].json
method: get
- delegate_to: localhost
register: nm_query_tenant
- name: Verify query_tenant
@@ -140,12 +158,10 @@
# REMOVE TENANT
- name: Remove tenant (normal mode)
cisco.aci.aci_rest: *tenant_absent
- delegate_to: localhost
register: nm_remove_tenant
- name: Remove tenant again (normal mode)
cisco.aci.aci_rest: *tenant_absent
- delegate_to: localhost
register: nm_remove_tenant_again
- name: Verify remove_tenant
@@ -157,7 +173,6 @@
# QUERY NON-EXISTING TENANT
- name: Query non-existing tenant (normal mode)
cisco.aci.aci_rest: *tenant_query
- delegate_to: localhost
register: nm_query_non_tenant
- name: Verify query_non_tenant
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml
index bbbd57cd4..7a1dfd8ce 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml
@@ -18,7 +18,7 @@
method: delete
# ADD TENANT
-- name: Add tenant (normal mode)
+- name: Add tenant (check mode)
cisco.aci.aci_rest: &tenant_present
host: '{{ aci_hostname }}'
username: '{{ aci_username }}'
@@ -38,6 +38,31 @@
}
}
output_path: "/tmp/ansible_output_file.log"
+ register: cm_add_tenant
+ check_mode: true
+
+- name: Verify checkmode did not create tenant
+ cisco.aci.aci_tenant:
+ 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: ansible_test
+ state: query
+ register: cm_verify_checkmode_tenant
+
+- name: Verify checkmode POST operation
+ assert:
+ that:
+ - cm_add_tenant is changed
+ - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test"
+ - cm_verify_checkmode_tenant.current == []
+
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_present
register: nm_add_tenant
- name: Add tenant again (normal mode)
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml
index 0952dd85b..c06f0cee2 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml
@@ -24,8 +24,8 @@
- include_tasks: xml_string.yml
tags: xml_string
-- include_tasks: error_handling.yml
- tags: error_handling
-
- include_tasks: xml_file.yml
tags: xml_file
+
+- include_tasks: error_handling.yml
+ tags: error_handling
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml
index cdde037c4..fea63112b 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml
@@ -32,10 +32,25 @@
check_mode: true
register: cm_add_tenant
+- name: Verify checkmode did not create tenant
+ cisco.aci.aci_tenant:
+ 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: ans_test_create
+ state: query
+ register: cm_verify_checkmode_tenant
+
- name: Assertions check for add tenant using ans_test_create xml template file with check mode
assert:
that:
- - cm_add_tenant is not changed
+ - cm_add_tenant is changed
+ - '"ans_test_create" in cm_add_tenant.proposed'
+ - cm_verify_checkmode_tenant.current == []
- name: Add tenant using ans_test_create xml template file with normal mode
cisco.aci.aci_rest:
@@ -95,7 +110,7 @@
- name: Assertions check for update tenant description using ans_test_update xml template file with check mode
assert:
that:
- - cm_update_tenant is not changed
+ - cm_update_tenant is changed
- name: Update tenant description using ans_test_update xml template file with normal mode
cisco.aci.aci_rest:
@@ -168,7 +183,7 @@
- name: Assertions check for delete tenant using ans_test_delete xml template file with check mode
assert:
that:
- - cm_delete_tenant is not changed
+ - cm_delete_tenant is changed
- name: Delete tenant using ans_test_delete xml template file with normal mode
cisco.aci.aci_rest:
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.json b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.json
new file mode 100644
index 000000000..b2d10f46a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.json
@@ -0,0 +1 @@
+{wrong_payload \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.xml
new file mode 100644
index 000000000..96877ed2d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/fail_parse.xml
@@ -0,0 +1 @@
+wrong_payload \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml
index c87291779..d1424bafa 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml
@@ -18,6 +18,66 @@
method: delete
# ADD TENANT
+- name: Add tenant (check mode)
+ cisco.aci.aci_rest:
+ 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") }}'
+ path: /api/mo/uni.xml
+ method: post
+ content:
+ <fvTenant name="ansible_test"/>
+ register: cm_add_tenant
+ check_mode: true
+
+- name: Add tenant 2 (check mode)
+ cisco.aci.aci_rest:
+ 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") }}'
+ path: /api/mo/uni.xml
+ method: post
+ content:
+ {
+ "fvTenant": {
+ "attributes": {
+ "name": "ansible_test"
+ }
+ }
+ }
+ register: cm_add_tenant_2
+ check_mode: true
+
+- name: Verify checkmode did not create tenant
+ cisco.aci.aci_tenant: &tenant_cm_query
+ 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: ansible_test
+ state: query
+ register: cm_verify_checkmode_tenant
+
+- name: Verify checkmode POST operation
+ assert:
+ that:
+ - cm_add_tenant is changed
+ - '"ansible_test" in cm_add_tenant.proposed'
+ - cm_add_tenant_2 is changed
+ - '"ansible_test" in cm_add_tenant.proposed'
+ - cm_verify_checkmode_tenant.current == []
+
- name: Add tenant (normal mode)
cisco.aci.aci_rest: &tenant_present
host: '{{ aci_hostname }}'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml
index d7538f9a6..6cd06afcd 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml
@@ -18,7 +18,7 @@
method: delete
# ADD TENANT
-- name: Add tenant (normal mode)
+- name: Add tenant (check mode)
cisco.aci.aci_rest: &tenant_present
host: '{{ aci_hostname }}'
username: '{{ aci_username }}'
@@ -33,6 +33,31 @@
fvTenant:
attributes:
name: ansible_test
+ register: cm_add_tenant
+ check_mode: true
+
+- name: Verify checkmode did not create tenant
+ cisco.aci.aci_tenant:
+ 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: ansible_test
+ state: query
+ register: cm_verify_checkmode_tenant
+
+- name: Verify checkmode POST operation
+ assert:
+ that:
+ - cm_add_tenant is changed
+ - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test"
+ - cm_verify_checkmode_tenant.current == []
+
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_present
register: nm_add_tenant
- name: Add tenant again (normal mode)
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml
index d7538f9a6..895045474 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml
@@ -18,7 +18,7 @@
method: delete
# ADD TENANT
-- name: Add tenant (normal mode)
+- name: Add tenant (check mode)
cisco.aci.aci_rest: &tenant_present
host: '{{ aci_hostname }}'
username: '{{ aci_username }}'
@@ -29,10 +29,35 @@
output_level: '{{ aci_output_level | default("info") }}'
path: /api/mo/uni.json
method: post
- content:
+ content: |
fvTenant:
attributes:
name: ansible_test
+ register: cm_add_tenant
+ check_mode: true
+
+- name: Verify checkmode did not create tenant
+ cisco.aci.aci_tenant:
+ 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: ansible_test
+ state: query
+ register: cm_verify_checkmode_tenant
+
+- name: Verify checkmode POST operation
+ assert:
+ that:
+ - cm_add_tenant is changed
+ - cm_add_tenant.proposed.fvTenant.attributes.name == "ansible_test"
+ - cm_verify_checkmode_tenant.current == []
+
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_present
register: nm_add_tenant
- name: Add tenant again (normal mode)
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml
new file mode 100644
index 000000000..83f46e4b8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_context/tasks/main.yml
@@ -0,0 +1,197 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+# Copyright: (c) 2023, Tim Cragg (@timcragg) <tcragg@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a new action rule profile
+ aci_tenant_action_rule_profile: &aci_action_rule_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ action_rule: ansible_action_rule
+ description: Ansible action rule profile for ansible_tenant tenant
+ state: present
+
+ - name: Add a new L3Out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ description: Ansible l3Out for ansible_tenant tenant
+ domain: ansible_dom
+ vrf: ansible_vrf
+ state: present
+
+ - name: Add a route control profile for l3out
+ aci_route_control_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ route_control_profile: ansible_rtctrl_profile_l3out
+ description: Ansible Route Control Profile for ansible_l3out l3Out
+ state: present
+
+ - name: Add a subject profile
+ aci_match_rule: &aci_match_rule_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ match_rule: ansible_match_rule
+ description: Ansible Subject Profile for ansible_tenant tenant
+ state: present
+
+ - name: Add a route control context policy for l3out (check_mode)
+ aci_route_control_context: &aci_route_control_context_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ route_control_profile: ansible_rtctrl_profile_l3out
+ route_control_context: ansible_route_control_context_l3out
+ description: Ansible route control Context Policy for ansible_rtctrl_profile_l3out route control profile
+ match_rule: ansible_match_rule
+ action_rule: ansible_action_rule
+ action: deny
+ order: 5
+ state: present
+ check_mode: true
+ register: cm_add_route_control_context_l3out
+
+ - name: Add a route control context policy again (normal_mode)
+ aci_route_control_context:
+ <<: *aci_route_control_context_present
+ register: nm_add_route_control_context_l3out
+
+ - name: Add a route control context policy again - testing idempotency
+ aci_route_control_context:
+ <<: *aci_route_control_context_present
+ register: nm_add_route_control_context_l3out_idempotency
+
+ - name: Add a route control profile for tenant
+ aci_route_control_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ route_control_profile: ansible_rtctrl_profile_tenant
+ description: Route Control Profile for ansible_tenant tenant
+ state: present
+
+ - name: Add a route control context policy for tenant
+ aci_route_control_context:
+ <<: *aci_info
+ tenant: ansible_tenant
+ route_control_profile: ansible_rtctrl_profile_tenant
+ route_control_context: ansible_route_control_context_tenant
+ description: Ansible route control Context Policy for ansible_rtctrl_profile_tenant route control profile
+ state: present
+ register: nm_add_route_control_context_tenant
+
+ - name: Asserts for route control profiles creation tasks
+ assert:
+ that:
+ - cm_add_route_control_context_l3out is changed
+ - cm_add_route_control_context_l3out.previous == []
+ - cm_add_route_control_context_l3out.current == []
+ - nm_add_route_control_context_l3out is changed
+ - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_route_control_context_l3out"
+ - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.attributes.action == "deny"
+ - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.attributes.order == "5"
+ - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tnRtctrlAttrPName == "ansible_action_rule"
+ - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tnRtctrlSubjPName == "ansible_match_rule"
+ - nm_add_route_control_context_l3out_idempotency is not changed
+ - nm_add_route_control_context_tenant is changed
+ - nm_add_route_control_context_tenant.previous == []
+ - nm_add_route_control_context_tenant.current.0.rtctrlCtxP.attributes.name == "ansible_route_control_context_tenant"
+ - nm_add_route_control_context_tenant.current.0.rtctrlCtxP.attributes.action == "permit"
+ - nm_add_route_control_context_tenant.current.0.rtctrlCtxP.attributes.order == "0"
+
+ - name: Query all route control context policies
+ aci_route_control_context:
+ <<: *aci_info
+ state: query
+ register: query_all_route_control_context
+
+ - name: Query ansible_route_control_context_l3out route control context policy
+ aci_route_control_context:
+ <<: *aci_info
+ route_control_context: ansible_route_control_context_l3out
+ state: query
+ register: query_route_control_context_l3out
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_route_control_context is not changed
+ - query_all_route_control_context.current|length >= 2
+ - query_route_control_context_l3out is not changed
+ - query_route_control_context_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_route_control_context_l3out"
+ - query_route_control_context_l3out.current.0.rtctrlCtxP.attributes.action == "deny"
+ - query_route_control_context_l3out.current.0.rtctrlCtxP.attributes.order == "5"
+ - query_route_control_context_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tDn == "uni/tn-ansible_tenant/attr-ansible_action_rule"
+ - query_route_control_context_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tDn == "uni/tn-ansible_tenant/subj-ansible_match_rule"
+
+ - name: Remove route control context policy for l3out (check_mode)
+ aci_route_control_context: &aci_route_control_context_absent
+ <<: *aci_route_control_context_present
+ state: absent
+ check_mode: true
+ register: cm_remove_route_control_context
+
+ - name: Remove route control context policy for l3out (normal_mode)
+ aci_route_control_context:
+ <<: *aci_route_control_context_absent
+ register: nm_remove_remove_route_control_context
+
+ - name: Remove route control profile for l3out again - testing previous Removal
+ aci_route_control_context:
+ <<: *aci_route_control_context_absent
+ register: nm_remove_route_control_context_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_route_control_context is changed
+ - cm_remove_route_control_context.proposed == {}
+ - nm_remove_remove_route_control_context is changed
+ - nm_remove_remove_route_control_context.previous != []
+ - nm_remove_remove_route_control_context.method == "DELETE"
+ - nm_remove_route_control_context_idempotency is not changed
+ - nm_remove_route_control_context_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml
new file mode 100644
index 000000000..db0022100
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_route_control_profile/tasks/main.yml
@@ -0,0 +1,145 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+# Copyright: (c) 2023, Tim Cragg (@timcragg) <tcragg@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant: &aci_tenant_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Add a new tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add a new L3Out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ description: L3Out for ansible_tenant tenant
+ domain: ansible_dom
+ vrf: ansible_vrf
+ state: present
+
+ - name: Add route control profile for l3out (check_mode)
+ aci_route_control_profile: &aci_route_control_profile_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ route_control_profile: ansible_rtctrl_profile_l3out
+ description: Route Control Profile for ansible_l3out L3Out
+ auto_continue: no
+ policy_type: combinable
+ state: present
+ check_mode: true
+ register: cm_add_route_control_profile
+
+ - name: Add route control profile for l3out (normal_mode)
+ aci_route_control_profile:
+ <<: *aci_route_control_profile_present
+ register: nm_add_route_control_profile
+
+ - name: Add route control profile for l3out again - testing idempotency
+ aci_route_control_profile:
+ <<: *aci_route_control_profile_present
+ register: nm_add_route_control_profile_idempotency
+
+ - name: Add route control profile for tenant (normal_mode)
+ aci_route_control_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ route_control_profile: ansible_rtctrl_profile_tenant
+ description: Route Control Profile for ansible_tenant tenant
+ state: present
+ register: nm_add_route_control_profile_2
+
+ - name: Asserts for route control profiles creation tasks
+ assert:
+ that:
+ - cm_add_route_control_profile is changed
+ - cm_add_route_control_profile.previous == []
+ - cm_add_route_control_profile.current == []
+ - nm_add_route_control_profile is changed
+ - nm_add_route_control_profile_idempotency is not changed
+ - nm_add_route_control_profile_2 is changed
+ - nm_add_route_control_profile_2.previous == []
+
+ - name: Query all route control profiles
+ aci_route_control_profile:
+ <<: *aci_info
+ state: query
+ register: query_all_route_control_profile
+
+ - name: Query ansible_rtctrl_profile_l3out
+ aci_route_control_profile:
+ <<: *aci_route_control_profile_present
+ state: query
+ register: query_ansible_rtctrl_profile_l3out
+
+ - name: Asserts query tasks
+ assert:
+ that:
+ - query_all_route_control_profile is not changed
+ - query_all_route_control_profile.current|length >= 2
+
+ - name: Remove route control profile for l3out (check_mode)
+ aci_route_control_profile: &route_control_profile_absent
+ <<: *aci_route_control_profile_present
+ state: absent
+ check_mode: true
+ register: cm_remove_route_control_profile
+
+ - name: Remove route control profile for l3out (normal_mode)
+ aci_route_control_profile:
+ <<: *route_control_profile_absent
+ register: nm_remove_route_control_profile
+
+ - name: Remove route control profile for l3out again - testing previous Removal
+ aci_route_control_profile:
+ <<: *route_control_profile_absent
+ register: nm_remove_route_control_profile_idempotency
+
+ - name: Asserts deletion tasks
+ assert:
+ that:
+ - cm_remove_route_control_profile is changed
+ - cm_remove_route_control_profile.proposed == {}
+ - nm_remove_route_control_profile is changed
+ - nm_remove_route_control_profile.previous != []
+ - nm_remove_route_control_profile.method == "DELETE"
+ - nm_remove_route_control_profile_idempotency is not changed
+ - nm_remove_route_control_profile_idempotency.previous == []
+
+ - name: Remove the ansible_tenant - cleanup before ending tests
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/tasks/main.yml
index 1b2608189..aabfd4c67 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/tasks/main.yml
@@ -1,16 +1,16 @@
# Test code for the ACI modules
# Copyright: (c) 2021, Tim Cragg (@timcragg)
+# Copyright: (c) 2023, Akini Ross (@akinross)
# 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:
+ 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
-# GET Credentials from the inventory
- name: Set vars
- set_fact:
+ ansible.builtin.set_fact:
aci_info: &aci_info
host: "{{ aci_hostname }}"
username: "{{ aci_username }}"
@@ -18,26 +18,25 @@
validate_certs: '{{ aci_validate_certs | default(false) }}'
use_ssl: '{{ aci_use_ssl | default(true) }}'
use_proxy: '{{ aci_use_proxy | default(true) }}'
- output_level: debug
+ output_level: '{{ aci_output_level | default("info") }}'
# CLEAN ENVIRONMENT
- name: Remove ansible_snmp_policy if it already exists
- aci_snmp_policy:
+ cisco.aci.aci_snmp_policy:
<<: *aci_info
name: ansible_snmp_policy
state: absent
-# ADD snmp policy
-- name: Add snmp policy
- aci_snmp_policy:
+# CREATE SNMP USER
+- name: Create snmp policy
+ cisco.aci.aci_snmp_policy:
<<: *aci_info
name: ansible_snmp_policy
admin_state: enabled
state: present
-# ADD snmp user
-- name: Add snmp user
- aci_snmp_user:
+- name: Create a snmp user (checkmode)
+ cisco.aci.aci_snmp_user: &snmp_user
<<: *aci_info
policy: ansible_snmp_policy
name: ansible_snmp_user
@@ -46,66 +45,223 @@
privacy_type: aes-128
privacy_key: "priv-test-key"
state: present
- register: add_snmp_user
+ register: cm_create_snmp_user
+ check_mode: true
-- name: Verify that ansible_snmp_community has been created with correct attributes
- assert:
+- name: Create a snmp user
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user
+ register: nm_create_snmp_user
+
+- name: Create a snmp user again without secrets
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user
+ auth_key: "{{ fake_var | default(omit) }}"
+ privacy_key: "{{ fake_var | default(omit) }}"
+ register: nm_create_snmp_user_again
+
+- name: Verify create of ansible_snmp_user
+ ansible.builtin.assert:
+ that:
+ - cm_create_snmp_user is changed
+ - cm_create_snmp_user.proposed.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - cm_create_snmp_user.proposed.snmpUserP.attributes.name == "ansible_snmp_user"
+ - cm_create_snmp_user.proposed.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - cm_create_snmp_user.proposed.snmpUserP.attributes.privType == "aes-128"
+ - cm_create_snmp_user.proposed.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - cm_create_snmp_user.previous == []
+ - nm_create_snmp_user is changed
+ - nm_create_snmp_user.current.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - nm_create_snmp_user.current.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_create_snmp_user.current.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - nm_create_snmp_user.current.0.snmpUserP.attributes.privType == "aes-128"
+ - nm_create_snmp_user.current.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - nm_create_snmp_user.current.0.snmpUserP.attributes.descr == ""
+ - nm_create_snmp_user.previous == []
+ - nm_create_snmp_user_again is not changed
+ - nm_create_snmp_user_again.previous.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - nm_create_snmp_user_again.previous.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_create_snmp_user_again.previous.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - nm_create_snmp_user_again.previous.0.snmpUserP.attributes.privType == "aes-128"
+ - nm_create_snmp_user_again.previous.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - nm_create_snmp_user_again.previous.0.snmpUserP.attributes.descr == ""
+ - nm_create_snmp_user_again.current.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - nm_create_snmp_user_again.current.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_create_snmp_user_again.current.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - nm_create_snmp_user_again.current.0.snmpUserP.attributes.privType == "aes-128"
+ - nm_create_snmp_user_again.current.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - nm_create_snmp_user_again.current.0.snmpUserP.attributes.descr == ""
+
+# CHANGE SNMP USER
+- name: Change a snmp user (checkmode)
+ cisco.aci.aci_snmp_user: &snmp_user_changed
+ <<: *snmp_user
+ descr: description_change
+ register: cm_change_snmp_user
+ check_mode: true
+
+- name: Change a snmp user
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user_changed
+ register: nm_change_snmp_user
+
+- name: Change a snmp user again without secrets
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user_changed
+ auth_key: "{{ fake_var | default(omit) }}"
+ privacy_key: "{{ fake_var | default(omit) }}"
+ register: nm_change_snmp_user_again
+
+- name: Verify change of ansible_snmp_user
+ ansible.builtin.assert:
that:
- - add_snmp_user.current.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
- - add_snmp_user.current.0.snmpUserP.attributes.name == "ansible_snmp_user"
- - add_snmp_user.current.0.snmpUserP.attributes.authType == "hmac-sha1-96"
- - add_snmp_user.current.0.snmpUserP.attributes.privType == "aes-128"
- - add_snmp_user.current.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
-
-# QUERY snmp user
-- name: Query snmp user
- aci_snmp_user:
+ - cm_change_snmp_user is changed
+ - cm_change_snmp_user.previous.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - cm_change_snmp_user.previous.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - cm_change_snmp_user.previous.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - cm_change_snmp_user.previous.0.snmpUserP.attributes.privType == "aes-128"
+ - cm_change_snmp_user.previous.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - cm_change_snmp_user.previous.0.snmpUserP.attributes.descr == ""
+ - cm_change_snmp_user.proposed.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - cm_change_snmp_user.proposed.snmpUserP.attributes.name == "ansible_snmp_user"
+ - cm_change_snmp_user.proposed.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - cm_change_snmp_user.proposed.snmpUserP.attributes.privType == "aes-128"
+ - cm_change_snmp_user.proposed.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - cm_change_snmp_user.proposed.snmpUserP.attributes.descr == "description_change"
+ - nm_change_snmp_user is changed
+ - nm_change_snmp_user.previous.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - nm_change_snmp_user.previous.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_change_snmp_user.previous.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - nm_change_snmp_user.previous.0.snmpUserP.attributes.privType == "aes-128"
+ - nm_change_snmp_user.previous.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - nm_change_snmp_user.previous.0.snmpUserP.attributes.descr == ""
+ - nm_change_snmp_user.current.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - nm_change_snmp_user.current.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_change_snmp_user.current.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - nm_change_snmp_user.current.0.snmpUserP.attributes.privType == "aes-128"
+ - nm_change_snmp_user.current.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - nm_change_snmp_user.current.0.snmpUserP.attributes.descr == "description_change"
+ - nm_change_snmp_user_again is not changed
+ - nm_change_snmp_user_again.previous.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - nm_change_snmp_user_again.previous.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_change_snmp_user_again.previous.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - nm_change_snmp_user_again.previous.0.snmpUserP.attributes.privType == "aes-128"
+ - nm_change_snmp_user_again.previous.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - nm_change_snmp_user_again.previous.0.snmpUserP.attributes.descr == "description_change"
+ - nm_change_snmp_user_again.current.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
+ - nm_change_snmp_user_again.current.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_change_snmp_user_again.current.0.snmpUserP.attributes.authType == "hmac-sha1-96"
+ - nm_change_snmp_user_again.current.0.snmpUserP.attributes.privType == "aes-128"
+ - nm_change_snmp_user_again.current.0.snmpUserP.attributes.annotation == 'orchestrator:ansible'
+ - nm_change_snmp_user_again.current.0.snmpUserP.attributes.descr == "description_change"
+
+# QUERY SNMP USER
+- name: Create another snmp user with auth_type hmac-sha2-224
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user
+ name: ansible_snmp_user_2
+ auth_type: hmac-sha2-224
+ register: nm_create_snmp_user_2
+
+- name: Create another snmp user with auth_type hmac-sha2-256
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user
+ name: ansible_snmp_user_3
+ auth_type: hmac-sha2-256
+ register: nm_create_snmp_user_3
+
+- name: Create another snmp user with auth_type hmac-sha2-384
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user
+ name: ansible_snmp_user_4
+ auth_type: hmac-sha2-384
+ register: nm_create_snmp_user_4
+
+- name: Create another snmp user with auth_type hmac-sha2-512
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user
+ name: ansible_snmp_user_5
+ auth_type: hmac-sha2-512
+ register: nm_create_snmp_user_5
+
+- name: Verify change of ansible_snmp_user
+ ansible.builtin.assert:
+ that:
+ - nm_create_snmp_user_2 is changed
+ - nm_create_snmp_user_2.current.0.snmpUserP.attributes.authType == "hmac-sha2-224"
+ - nm_create_snmp_user_3 is changed
+ - nm_create_snmp_user_3.current.0.snmpUserP.attributes.authType == "hmac-sha2-256"
+ - nm_create_snmp_user_4 is changed
+ - nm_create_snmp_user_4.current.0.snmpUserP.attributes.authType == "hmac-sha2-384"
+ - nm_create_snmp_user_5 is changed
+ - nm_create_snmp_user_5.current.0.snmpUserP.attributes.authType == "hmac-sha2-512"
+
+- name: Query ansible_snmp_user
+ cisco.aci.aci_snmp_user:
<<: *aci_info
policy: ansible_snmp_policy
name: ansible_snmp_user
state: query
register: query_snmp_user
-- name: Verify the attributes under query_snmp_client_group
- assert:
+- name: Verify query of ansible_snmp_user
+ ansible.builtin.assert:
that:
- query_snmp_user is not changed
+ - query_snmp_user.current | length == 1
- query_snmp_user.current.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
- query_snmp_user.current.0.snmpUserP.attributes.name == "ansible_snmp_user"
- query_snmp_user.current.0.snmpUserP.attributes.authType == "hmac-sha1-96"
- query_snmp_user.current.0.snmpUserP.attributes.privType == "aes-128"
-- name: Query all snmp communities
- aci_snmp_user:
+- name: Query all snmp users
+ cisco.aci.aci_snmp_user:
<<: *aci_info
state: query
register: query_snmp_user_all
-- name: Verify query_snmp_user_all
- assert:
+- name: Verify query of all snmp users
+ ansible.builtin.assert:
that:
- query_snmp_user_all is not changed
+ - query_snmp_user_all.current | length >= 5
-# DELETE snmp user
-- name: Remove the snmp user
- aci_snmp_user:
+# REMOVE SNMP USER
+- name: Remove the snmp user (checkmode)
+ cisco.aci.aci_snmp_user: &snmp_user_remove
<<: *aci_info
policy: ansible_snmp_policy
name: ansible_snmp_user
state: absent
- register: remove_snmp_user
+ register: cm_remove_snmp_user
+ check_mode: true
+
+- name: Remove the snmp user
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user_remove
+ register: nm_remove_snmp_user
+
+- name: Remove the snmp user again
+ cisco.aci.aci_snmp_user:
+ <<: *snmp_user_remove
+ register: nm_remove_snmp_user_again
- name: Verify remove_snmp_user
- assert:
+ ansible.builtin.assert:
that:
- - remove_snmp_user is changed
- - remove_snmp_user.current == []
- - remove_snmp_user.previous.0.snmpUserP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/user-ansible_snmp_user"
- - remove_snmp_user.previous.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - cm_remove_snmp_user is changed
+ - cm_remove_snmp_user.previous.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - cm_remove_snmp_user.proposed == {}
+ - nm_remove_snmp_user is changed
+ - nm_remove_snmp_user.current == []
+ - nm_remove_snmp_user.previous.0.snmpUserP.attributes.name == "ansible_snmp_user"
+ - nm_remove_snmp_user_again is not changed
+ - nm_remove_snmp_user_again.current == []
+ - nm_remove_snmp_user_again.previous == []
-# DELETE snmp policy
+# CLEAN ENVIRONMENT
- name: Remove the snmp policy
- aci_snmp_policy:
+ cisco.aci.aci_snmp_policy:
<<: *aci_info
name: ansible_snmp_policy
state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml
index 180848e28..0e9096b85 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml
@@ -306,7 +306,7 @@
- 104
- 105
ignore_errors: true
- register: fex_vpc_three extpaths
+ register: fex_vpc_three_extpaths
- name: Bind static-binding to epg - fex_port_channel with multiple extpaths (check_mode)
cisco.aci.aci_static_binding_to_epg:
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml
index 0840aec20..82839ddf7 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml
@@ -46,7 +46,6 @@
facility: local1
syslog_port: 5678
description: ansible syslog remote destination
- mgmt_epg: oob-default
format: aci
admin_state: enabled
severity: warnings
@@ -66,11 +65,7 @@
- add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.adminState == "enabled"
- add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.severity == "warnings"
- add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.annotation == 'orchestrator:ansible'
-
-- name: Verify that ansible_syslog_remote_dest children have correct attributes
- assert:
- that:
- - add_syslog_remote_dest.current.0.syslogRemoteDest.children.0.fileRsARemoteHostToEpg.attributes.tDn == "uni/tn-mgmt/mgmtp-default/oob-default"
+ - '"children" not in add_syslog_remote_dest.current.0.syslogRemoteDest'
# ADD syslog remote dest again to check idempotency
- name: Add syslog remote dest
@@ -82,7 +77,6 @@
facility: local1
syslog_port: 5678
description: ansible syslog remote destination
- mgmt_epg: oob-default
format: aci
admin_state: enabled
severity: warnings
@@ -124,6 +118,11 @@
- update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.adminState == "disabled"
- update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.severity == "information"
+- name: Verify that ansible_syslog_remote_dest children have correct attributes
+ assert:
+ that:
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.children.0.fileRsARemoteHostToEpg.attributes.tDn == "uni/tn-mgmt/mgmtp-default/oob-default"
+
# QUERY syslog source
- name: Query the syslog source
aci_syslog_remote_dest:
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml
index c237d17fe..a7180649f 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml
@@ -40,10 +40,6 @@
aci_syslog_source:
<<: *aci_info
name: ansible_syslog_src
- include:
- - audit
- - events
- - faults
min_severity: errors
destination_group: ansible_syslog_group
state: present
@@ -54,7 +50,7 @@
that:
- add_syslog_src.current.0.syslogSrc.attributes.dn == "uni/fabric/moncommon/slsrc-ansible_syslog_src"
- add_syslog_src.current.0.syslogSrc.attributes.name == "ansible_syslog_src"
- - add_syslog_src.current.0.syslogSrc.attributes.incl == "audit,events,faults"
+ - add_syslog_src.current.0.syslogSrc.attributes.incl == "faults"
- add_syslog_src.current.0.syslogSrc.attributes.minSev == "errors"
- add_syslog_src.current.0.syslogSrc.attributes.annotation == 'orchestrator:ansible'
@@ -68,10 +64,6 @@
aci_syslog_source:
<<: *aci_info
name: ansible_syslog_src
- include:
- - audit
- - events
- - faults
min_severity: errors
destination_group: ansible_syslog_group
state: present
@@ -88,7 +80,9 @@
<<: *aci_info
name: ansible_syslog_src
include:
- - faults
+ - audit
+ - events
+ - faults
min_severity: information
destination_group: ansible_syslog_group
state: present
@@ -99,7 +93,7 @@
that:
- update_syslog_src.current.0.syslogSrc.attributes.dn == "uni/fabric/moncommon/slsrc-ansible_syslog_src"
- update_syslog_src.current.0.syslogSrc.attributes.name == "ansible_syslog_src"
- - update_syslog_src.current.0.syslogSrc.attributes.incl == "faults"
+ - update_syslog_src.current.0.syslogSrc.attributes.incl == "audit,events,faults"
- update_syslog_src.current.0.syslogSrc.attributes.minSev == "information"
# QUERY syslog source
@@ -116,7 +110,7 @@
- query_syslog_src is not changed
- query_syslog_src.current.0.syslogSrc.attributes.dn == "uni/fabric/moncommon/slsrc-ansible_syslog_src"
- query_syslog_src.current.0.syslogSrc.attributes.name == "ansible_syslog_src"
- - query_syslog_src.current.0.syslogSrc.attributes.incl == "faults"
+ - query_syslog_src.current.0.syslogSrc.attributes.incl == "audit,events,faults"
- query_syslog_src.current.0.syslogSrc.attributes.minSev == "information"
- name: Query all syslog sources
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml
new file mode 100644
index 000000000..5b9cb96f0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_banner/tasks/main.yml
@@ -0,0 +1,221 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Tim Cragg (@timcragg)
+# Copyright: (c) 2023, Akini Ross (@akinross)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# CLEANUP ENVIRONMENT
+- name: Clear the current alias and banner configuration
+ cisco.aci.aci_system_banner: &aci_banner_clear
+ <<: *aci_info
+ annotation: ""
+ gui_alias: ""
+ controller_banner: ""
+ application_banner: ""
+ severity: info
+ switch_banner: ""
+ gui_banner: ""
+
+# UPDATE ALIAS AND BANNER CONFIGURATION
+- name: Update alias and banner configuration (check mode)
+ cisco.aci.aci_system_banner: &aci_banner
+ <<: *aci_info
+ gui_alias: "Ansible Test GUI Alias"
+ controller_banner: "Ansible Test Controller Banner"
+ application_banner: "Ansible Test Application Banner"
+ severity: critical
+ switch_banner: "Ansible Test Switch Banner"
+ gui_banner: "Ansible Test GUI Banner"
+ check_mode: true
+ register: cm_update_banner
+
+- name: Update alias and banner configuration
+ cisco.aci.aci_system_banner:
+ <<: *aci_banner
+ register: nm_update_banner
+
+- name: Update alias and banner configuration again
+ cisco.aci.aci_system_banner:
+ <<: *aci_banner
+ register: nm_update_banner_again
+
+- name: Verify alias and banner configuration
+ ansible.builtin.assert:
+ that:
+ - cm_update_banner is changed
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.guiMessage == "Ansible Test GUI Banner"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.isGuiMessageText == "yes"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - cm_update_banner.proposed.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.annotation == ""
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.bannerMessage == ""
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "info"
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.guiMessage == ""
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.isGuiMessageText == "yes"
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.guiTextMessage == ""
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.message == ""
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.showBannerMessage == "no"
+ - cm_update_banner.current.0.aaaPreLoginBanner.attributes.switchMessage == ""
+ - nm_update_banner is changed
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.guiMessage == "Ansible Test GUI Banner"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.isGuiMessageText == "yes"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - nm_update_banner.current.0.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.annotation == ""
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.bannerMessage == ""
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "info"
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.guiMessage == ""
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.isGuiMessageText == "yes"
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.guiTextMessage == ""
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.message == ""
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.showBannerMessage == "no"
+ - nm_update_banner.previous.0.aaaPreLoginBanner.attributes.switchMessage == ""
+ - nm_update_banner_again is not changed
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.guiMessage == "Ansible Test GUI Banner"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.isGuiMessageText == "yes"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - nm_update_banner_again.current.0.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.guiMessage == "Ansible Test GUI Banner"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.isGuiMessageText == "yes"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - nm_update_banner_again.previous.0.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+
+- name: Update alias and banner configuration with http url
+ cisco.aci.aci_system_banner:
+ <<: *aci_banner
+ gui_banner: http://www.cisco.com
+ register: nm_update_banner_with_url_http
+
+- name: Update alias and banner configuration with https url
+ cisco.aci.aci_system_banner:
+ <<: *aci_banner
+ gui_banner: https://www.cisco.com
+ register: nm_update_banner_with_url_https
+
+- name: Verify alias and banner configuration with url
+ ansible.builtin.assert:
+ that:
+ - nm_update_banner_with_url_http is changed
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.guiMessage == "http://www.cisco.com"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.isGuiMessageText == "no"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - nm_update_banner_with_url_http.current.0.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.guiMessage == "Ansible Test GUI Banner"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.isGuiMessageText == "yes"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - nm_update_banner_with_url_http.previous.0.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+ - nm_update_banner_with_url_https is changed
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.guiMessage == "https://www.cisco.com"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.isGuiMessageText == "no"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - nm_update_banner_with_url_https.current.0.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.guiMessage == "http://www.cisco.com"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.isGuiMessageText == "no"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+ - nm_update_banner_with_url_https.previous.0.aaaPreLoginBanner.attributes.switchMessage == "Ansible Test Switch Banner"
+
+# QUERY ALIAS AND BANNER CONFIGURATION
+- name: Query alias and banner configuration
+ cisco.aci.aci_system_banner:
+ <<: *aci_banner
+ state: query
+ register: query
+
+- name: Verify alias and banner configuration query
+ ansible.builtin.assert:
+ that:
+ - query is not changed
+ - query.current.0.aaaPreLoginBanner.attributes.annotation == "orchestrator:ansible"
+ - query.current.0.aaaPreLoginBanner.attributes.bannerMessage == "Ansible Test Application Banner"
+ - query.current.0.aaaPreLoginBanner.attributes.bannerMessageSeverity == "critical"
+ - query.current.0.aaaPreLoginBanner.attributes.dn == "uni/userext/preloginbanner"
+ - query.current.0.aaaPreLoginBanner.attributes.guiMessage == "https://www.cisco.com"
+ - query.current.0.aaaPreLoginBanner.attributes.isGuiMessageText == "no"
+ - query.current.0.aaaPreLoginBanner.attributes.guiTextMessage == "Ansible Test GUI Alias"
+ - query.current.0.aaaPreLoginBanner.attributes.message == "Ansible Test Controller Banner"
+ - query.current.0.aaaPreLoginBanner.attributes.showBannerMessage == "yes"
+
+# ERROR ALIAS AND BANNER CONFIGURATION INPUT
+- name: Update alias and banner configuration (error)
+ cisco.aci.aci_system_banner:
+ <<: *aci_info
+ severity: critical
+ ignore_errors: true
+ register: err_update_banner_severity
+
+- name: Verify alias and banner configuration error
+ ansible.builtin.assert:
+ that:
+ - err_update_banner_severity is failed
+ - err_update_banner_severity.msg == "missing parameter(s) required by 'severity'{{":"}} application_banner"
+
+# CLEANUP ENVIRONMENT
+- name: Clear the current alias and banner configuration
+ cisco.aci.aci_system_banner:
+ <<: *aci_banner_clear
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml
new file mode 100644
index 000000000..fa98657f6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_endpoint_controls/tasks/main.yml
@@ -0,0 +1,307 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Tim Cragg (@timcragg)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+- 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 skip execution for cloud sites
+ block:
+
+ # CONFIGURE SYSTEM ENDPOINT CONTROLS SETTINGS TO DEFAULT
+ - name: Set system endpoint controls settings to default prior to test
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ ip_aging:
+ admin_state: false
+ roque_ep_control:
+ admin_state: false
+ interval: 60
+ multiplication_factor: 4
+ hold_interval: 1800
+ ep_loop_protection:
+ admin_state: false
+ interval: 60
+ multiplication_factor: 4
+ action: [ port ]
+
+ # CONFIGURE SYSTEM ENDPOINT CONTROLS SETTINGS
+ - name: Set system endpoint controls settings (check_mode)
+ cisco.aci.aci_system_endpoint_controls: &endpoint_controls
+ <<: *aci_info
+ ip_aging:
+ admin_state: true
+ roque_ep_control:
+ admin_state: true
+ interval: 50
+ multiplication_factor: 10
+ hold_interval: 2000
+ ep_loop_protection:
+ admin_state: true
+ interval: 70
+ multiplication_factor: 15
+ action: [ bd, port ]
+ check_mode: true
+ register: cm_set_endpoint_controls
+
+ - name: Set system endpoint controls settings
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *endpoint_controls
+ register: nm_set_endpoint_controls
+
+ - name: Set system endpoint controls settings again
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *endpoint_controls
+ register: nm_set_endpoint_controls_again
+
+ - name: Verify set system endpoint controls
+ ansible.builtin.assert:
+ that:
+ - cm_set_endpoint_controls is changed
+ - cm_set_endpoint_controls.proposed.infraInfra.children.0.epIpAgingP.attributes.adminSt == "enabled"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.1.epControlP.attributes.adminSt == "enabled"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.1.epControlP.attributes.name == "default"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.1.epControlP.attributes.holdIntvl == "2000"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "50"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "10"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - cm_set_endpoint_controls.proposed.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_set_endpoint_controls is changed
+ - nm_set_endpoint_controls.current.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "2000"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "50"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "10"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_set_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_set_endpoint_controls_again is not changed
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.1.epControlP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "2000"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "50"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "10"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_set_endpoint_controls_again.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.1.epControlP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "2000"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "50"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "10"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_set_endpoint_controls_again.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+
+ - name: Set ip aging system endpoint controls settings to default
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ ip_aging:
+ admin_state: false
+ register: nm_ip_aging
+
+ - name: Set roque ep control system endpoint controls settings to default
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ roque_ep_control:
+ admin_state: false
+ interval: 60
+ multiplication_factor: 4
+ hold_interval: 1800
+ register: nm_roque_ep_control
+
+ - name: Set ep loop protection system endpoint controls settings without action to default
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ ep_loop_protection:
+ admin_state: false
+ interval: 60
+ multiplication_factor: 4
+ register: nm_ep_loop_protection_no_action
+
+ - name: Set ep loop protection system endpoint controls settings action to default
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ ep_loop_protection:
+ action: port
+ register: nm_ep_loop_protection_action
+
+ - name: Set system endpoint controls settings without config in config containers
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ ip_aging:
+ roque_ep_control:
+ ep_loop_protection:
+ register: nm_no_config_in_config_containers
+
+ - name: Set system endpoint controls settings without config (error)
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ register: err_no_config
+ ignore_errors: true
+
+ - name: Verify individual set system endpoint controls and error
+ ansible.builtin.assert:
+ that:
+ - nm_ip_aging is changed
+ - nm_ip_aging.previous.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "enabled"
+ - nm_ip_aging.previous.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_ip_aging.previous.0.infraInfra.children.1.epControlP.attributes.adminSt == "enabled"
+ - nm_ip_aging.previous.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_ip_aging.previous.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "2000"
+ - nm_ip_aging.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "50"
+ - nm_ip_aging.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "10"
+ - nm_ip_aging.previous.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_ip_aging.previous.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_ip_aging.previous.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_ip_aging.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_ip_aging.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_ip_aging.current.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - nm_ip_aging.current.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_ip_aging.current.0.infraInfra.children.1.epControlP.attributes.adminSt == "enabled"
+ - nm_ip_aging.current.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_ip_aging.current.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "2000"
+ - nm_ip_aging.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "50"
+ - nm_ip_aging.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "10"
+ - nm_ip_aging.current.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_ip_aging.current.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_ip_aging.current.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_ip_aging.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_ip_aging.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_roque_ep_control is changed
+ - nm_roque_ep_control.previous.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - nm_roque_ep_control.previous.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_roque_ep_control.previous.0.infraInfra.children.1.epControlP.attributes.adminSt == "enabled"
+ - nm_roque_ep_control.previous.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_roque_ep_control.previous.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "2000"
+ - nm_roque_ep_control.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "50"
+ - nm_roque_ep_control.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "10"
+ - nm_roque_ep_control.previous.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_roque_ep_control.previous.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_roque_ep_control.previous.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_roque_ep_control.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_roque_ep_control.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_roque_ep_control.current.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - nm_roque_ep_control.current.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_roque_ep_control.current.0.infraInfra.children.1.epControlP.attributes.adminSt == "disabled"
+ - nm_roque_ep_control.current.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_roque_ep_control.current.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "1800"
+ - nm_roque_ep_control.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "60"
+ - nm_roque_ep_control.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "4"
+ - nm_roque_ep_control.current.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_roque_ep_control.current.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_roque_ep_control.current.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_roque_ep_control.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_roque_ep_control.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_ep_loop_protection_no_action is changed
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.1.epControlP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "1800"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "60"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "4"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "enabled"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "70"
+ - nm_ep_loop_protection_no_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "15"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.1.epControlP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "1800"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "60"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "4"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "60"
+ - nm_ep_loop_protection_no_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "4"
+ - nm_ep_loop_protection_action is changed
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.1.epControlP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "1800"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "60"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "4"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.action == "bd-learn-disable,port-disable"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "60"
+ - nm_ep_loop_protection_action.previous.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "4"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.1.epControlP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "1800"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "60"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "4"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "disabled"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.action == "port-disable"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "60"
+ - nm_ep_loop_protection_action.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "4"
+ - nm_no_config_in_config_containers is not changed
+ - err_no_config is not changed
+ - err_no_config is failed
+ - err_no_config.msg == "state is present but any of the following are missing{{":"}} ip_aging, roque_ep_control, ep_loop_protection"
+
+ # QUERY SYSTEM ENDPOINT CONTROLS SETTINGS
+ - name: Query system endpoint controls settings
+ cisco.aci.aci_system_endpoint_controls:
+ <<: *aci_info
+ state: query
+ register: query_endpoint_controls
+
+ - name: Verify system endpoint controls query
+ ansible.builtin.assert:
+ that:
+ - query_endpoint_controls is not changed
+ - query_endpoint_controls.current.0.infraInfra.children.0.epIpAgingP.attributes.adminSt == "disabled"
+ - query_endpoint_controls.current.0.infraInfra.children.0.epIpAgingP.attributes.name == "default"
+ - query_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.adminSt == "disabled"
+ - query_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.name == "default"
+ - query_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.holdIntvl == "1800"
+ - query_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectIntvl == "60"
+ - query_endpoint_controls.current.0.infraInfra.children.1.epControlP.attributes.rogueEpDetectMult == "4"
+ - query_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.adminSt == "disabled"
+ - query_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.name == "default"
+ - query_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.action == "port-disable"
+ - query_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectIntvl == "60"
+ - query_endpoint_controls.current.0.infraInfra.children.2.epLoopProtectP.attributes.loopDetectMult == "4"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml
new file mode 100644
index 000000000..732a4d4f3
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system_global_aes_passphrase_encryption/tasks/main.yml
@@ -0,0 +1,84 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Tim Cragg (@timcragg) <tcragg@cisco.com>
+# Copyright: (c) 2023, Akini Ross (@akinross) <akinross@cisco.com>
+
+# 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
+
+# SET VARS
+- 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: 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 skip execution for cloud sites
+ block:
+
+ - name: Clear existing passphrase
+ cisco.aci.aci_system_global_aes_passphrase_encryption:
+ <<: *aci_info
+ state: absent
+
+ - name: Set passphrase
+ cisco.aci.aci_system_global_aes_passphrase_encryption:
+ <<: *aci_info
+ passphrase: ansible_passphrase
+ state: present
+
+ - name: Query key configured
+ cisco.aci.aci_system_global_aes_passphrase_encryption:
+ <<: *aci_info
+ state: query
+ register: query_passphrase
+
+ - name: Enable encryption
+ cisco.aci.aci_system_global_aes_passphrase_encryption:
+ <<: *aci_info
+ enable: yes
+ state: present
+
+ - name: Query encryption enabled
+ cisco.aci.aci_system_global_aes_passphrase_encryption:
+ <<: *aci_info
+ state: query
+ register: query_encryption
+
+ - name: Verify passphrase and encryption settings
+ ansible.builtin.assert:
+ that:
+ - query_passphrase.current.0.pkiExportEncryptionKey.attributes.keyConfigured == "yes"
+ - query_passphrase.current.0.pkiExportEncryptionKey.attributes.strongEncryptionEnabled == "no"
+ - query_encryption.current.0.pkiExportEncryptionKey.attributes.keyConfigured == "yes"
+ - query_encryption.current.0.pkiExportEncryptionKey.attributes.strongEncryptionEnabled == "yes"
+
+ # CLEAR PASSPHRASE
+ - name: Clear encryption key
+ cisco.aci.aci_system_global_aes_passphrase_encryption:
+ <<: *aci_info
+ state: absent
+
+ - name: Query cleared encryption key
+ cisco.aci.aci_system_global_aes_passphrase_encryption:
+ <<: *aci_info
+ state: query
+ register: query_deletion
+
+ - name: Verify encryption key is deleted
+ ansible.builtin.assert:
+ that:
+ - query_deletion.current.0.pkiExportEncryptionKey.attributes.keyConfigured == "no"
+ - query_deletion.current.0.pkiExportEncryptionKey.attributes.strongEncryptionEnabled == "no"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/filter_plugins/generate_ips.py b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/filter_plugins/generate_ips.py
new file mode 100644
index 000000000..130fbb786
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/filter_plugins/generate_ips.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2023 Cisco and/or its affiliates.
+# Copyright: (c) 2023, Shreyas Srish (@shrsr) <ssrish@cisco.com>
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ipaddress import ip_network
+import random
+
+RANGE_IPV4 = list(ip_network("192.0.2.0/24").hosts()) + list(ip_network("198.51.100.0/24").hosts()) + list(ip_network("203.0.113.0/24").hosts())
+
+
+class FilterModule(object):
+ def filters(self):
+ return {
+ "generate_random_ips": self.generate_random_ips,
+ }
+
+ def generate_random_ips(self, given_ip, insert_given_ip_at, number_of_ips):
+ ips = ""
+ for i in range(number_of_ips):
+ if i == insert_given_ip_at - 1:
+ ips += given_ip
+ else:
+ ips += str((random.choice(RANGE_IPV4)))
+ ips += ","
+ return ips.rstrip(",")
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.crt
new file mode 100644
index 000000000..cfac5531e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICODCCAaGgAwIBAgIJAIt8XMntue0VMA0GCSqGSIb3DQEBCwUAMDQxDjAMBgNV
+BAMMBUFkbWluMRUwEwYDVQQKDAxZb3VyIENvbXBhbnkxCzAJBgNVBAYTAlVTMCAX
+DTE4MDEwOTAwNTk0NFoYDzIxMTcxMjE2MDA1OTQ0WjA0MQ4wDAYDVQQDDAVBZG1p
+bjEVMBMGA1UECgwMWW91ciBDb21wYW55MQswCQYDVQQGEwJVUzCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAohG/7axtt7CbSaMP7r+2mhTKbNgh0Ww36C7Ta14i
+v+VmLyKkQHnXinKGhp6uy3Nug+15a+eIu7CrgpBVMQeCiWfsnwRocKcQJWIYDrWl
+XHxGQn31yYKR6mylE7Dcj3rMFybnyhezr5D8GcP85YRPmwG9H2hO/0Y1FUnWu9Iw
+AQkCAwEAAaNQME4wHQYDVR0OBBYEFD0jLXfpkrU/ChzRvfruRs/fy1VXMB8GA1Ud
+IwQYMBaAFD0jLXfpkrU/ChzRvfruRs/fy1VXMAwGA1UdEwQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADgYEAOmvre+5tgZ0+F3DgsfxNQqLTrGiBgGCIymPkP/cBXXkNuJyl
+3ac7tArHQc7WEA4U2R2rZbEq8FC3UJJm4nUVtCPvEh3G9OhN2xwYev79yt6pIn/l
+KU0Td2OpVyo0eLqjoX5u2G90IBWzhyjFbo+CcKMrSVKj1YOdG0E3OuiJf00=
+-----END CERTIFICATE-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.key
new file mode 100644
index 000000000..63bb00cc0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin.key
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKIRv+2sbbewm0mj
+D+6/tpoUymzYIdFsN+gu02teIr/lZi8ipEB514pyhoaerstzboPteWvniLuwq4KQ
+VTEHgoln7J8EaHCnECViGA61pVx8RkJ99cmCkepspROw3I96zBcm58oXs6+Q/BnD
+/OWET5sBvR9oTv9GNRVJ1rvSMAEJAgMBAAECgYByu3QO0qF9h7X3JEu0Ld4cKBnB
+giQ2uJC/et7KxIJ/LOvw9GopBthyt27KwG1ntBkJpkTuAaQHkyNns7vLkNB0S0IR
++owVFEcKYq9VCHTaiQU8TDp24gN+yPTrpRuH8YhDVq5SfVdVuTMgHVQdj4ya4VlF
+Gj+a7+ipxtGiLsVGrQJBAM7p0Fm0xmzi+tBOASUAcVrPLcteFIaTBFwfq16dm/ON
+00Khla8Et5kMBttTbqbukl8mxFjBEEBlhQqb6EdQQ0sCQQDIhHx1a9diG7y/4DQA
+4KvR3FCYwP8PBORlSamegzCo+P1OzxiEo0amX7yQMA5UyiP/kUsZrme2JBZgna8S
+p4R7AkEAr7rMhSOPUnMD6V4WgsJ5g1Jp5kqkzBaYoVUUSms5RASz4+cwJVCwTX91
+Y1jcpVIBZmaaY3a0wrx13ajEAa0dOQJBAIpjnb4wqpsEh7VpmJqOdSdGxb1XXfFQ
+sA0T1OQYqQnFppWwqrxIL+d9pZdiA1ITnNqyvUFBNETqDSOrUHwwb2cCQGArE+vu
+ffPUWQ0j+fiK+covFG8NL7H+26NSGB5+Xsn9uwOGLj7K/YT6CbBtr9hJiuWjM1Al
+0V4ltlTuu2mTMaw=
+-----END PRIVATE KEY-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin_invalid.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin_invalid.key
new file mode 100644
index 000000000..22f5fae45
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/admin_invalid.key
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+This is an invalid private key
+-----END PRIVATE KEY-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/openssh_rsa.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/openssh_rsa.key
new file mode 100644
index 000000000..0c18da5c5
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/openssh_rsa.key
@@ -0,0 +1,16 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAIEA3VnrdPOQbr3DPF5GbC31W7ScloEpU9BSDqPmpyYPUdsWl21UXBB8
+exip3GVOl+7GbB1WkDKYr7uMuBjsfDzMzZkDAFVEpud+IUzZB7aSfSd+L9bdeFG2sGI+Fv
+y1QmiMBT5gcvXaM16vRKe4FywM07/Fmd3REm/+wtmFG/C4sYUAAAIQLuIWNS7iFjUAAAAH
+c3NoLXJzYQAAAIEA3VnrdPOQbr3DPF5GbC31W7ScloEpU9BSDqPmpyYPUdsWl21UXBB8ex
+ip3GVOl+7GbB1WkDKYr7uMuBjsfDzMzZkDAFVEpud+IUzZB7aSfSd+L9bdeFG2sGI+Fvy1
+QmiMBT5gcvXaM16vRKe4FywM07/Fmd3REm/+wtmFG/C4sYUAAAADAQABAAAAgHj5rhALFg
+MQP2X8+GwjahemzHYNPXMLRe2ucl8kE/de0CgOnq56bC4yupMz4xJyc4ufNTI2FPDmhfAP
+3x+/cwZeYFsipyGdL1IYbfk0QYSP65Btr2yq8+QyN7zWdFXQ8csT0ImZgNiQKehc69ctLH
+XcyelsdwNiUCRZYa7kCpf5AAAAQQCo7OSWQUa16xP9KrKm0F3fnaAKewhQNDIwok5PRgoN
+03k/IpGOCAjvNuOb7DkXmVvxjO8Rj4L16vL+RTzHg8n7AAAAQQD7tej6gJy3MLcmrQ4aHb
+FeLzQ/ZXS2IgdIRC8rcNB1h9Rso7+fySVFwnmwy2Um7wwsjNnr2xyhigwfQCSyRubfAAAA
+QQDhH5EX7+hdm/fPLM6Goz9N3ERbIgBq2Mel5CCi/Ns7vDfBQiEla1atdKTV0S2EYfxIw2
+ehkMGbmXl2/9JHxKgbAAAAFGNpemhhb0BDSVpIQU8tTS05MjhRAQIDBAUG
+-----END OPENSSH PRIVATE KEY-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_ansible.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_ansible.key
new file mode 100644
index 000000000..ac63a0055
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_ansible.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDVyLS8/ix6QOH7R83B4WuhsliL6nffBvrkHXXsqViit3OZd+/K
+fSrNlZysUvHS4hxfRtJrFQfpkogwXEEupBPF3p0xy7wZzvjjWWJk0NQ8PoVlOhUY
+emZTfMX+FFNr9pAjjjaVHb9jCuxko7upAyj8POhhETY2zYoJoa8TR6fLZwIDAQAB
+AoGBALo5GzeGMThNTIyW/6Tjt94ifP9kPwcIDYSoJRECczNKmmgVEcxRO/fZW6DA
+n+YTEKPuDV059KqB+iAmPKFkS9N41kaq+NUAknlFJPV6Vs3gpvJGqWgu++73dhR5
+cKsHTlK2KBsRtsXnOJ9odKWFjiTnZ1Eyvmhw7ct+Fojb/7ABAkEA9+Wwm+HGlYqw
+ghuFaBtNuqC/S2vO6SEfdQvTDQKKO5ROei5m+ryjWj6flbCcG+5dLs8l4Zh3sQUL
+kc0RQfHSWQJBANzFkdO6wXXPOw7RhAEP2sA2W2VacMbGynjsoDJXmypeJ7Z+odLb
+5gNXET9RA77RY/saIBdwR4JNnku2WnoxU78CQQDhYirVP0vu8H6UfHMpeRGNqdLi
+vq0LlrrkDxEe1f1aN/e17HRiaZnXVfKABWeZmXmNMndNifLgtiaTtC+JllRZAkEA
+ydAdV0SANvaCETC7j9DzcgP+lm8PatYsHlCIvJxS7m71tKCbw0pbQDBmRtADMXrt
+/4vJTEPKSrYzfxiqKstOtwJAXkWXaqVhJeKjbMj1buo6s/1qGIfSrZR/AjozvJ03
+JehevfULS3668jOYJZW6BoNhysx6+Hqf5Id8fB4iDWPQhA==
+-----END RSA PRIVATE KEY-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.crt
new file mode 100644
index 000000000..de2223500
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.crt
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICODCCAaGgAwIBAgIUNOqiIBh811X/tPWSUgr9rajJ7t4wDQYJKoZIhvcNAQEL
+BQAwLTEOMAwGA1UEAwwFQWRtaW4xDjAMBgNVBAoMBWNpc2NvMQswCQYDVQQGEwJV
+UzAgFw0yMDEwMjkyMjQ0NTNaGA8yMTIwMTAwNTIyNDQ1M1owLTEOMAwGA1UEAwwF
+QWRtaW4xDjAMBgNVBAoMBWNpc2NvMQswCQYDVQQGEwJVUzCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAwjb3/W3x/bPX+bylh2PjXbcFPwpdTPJwqTxCdUinJRKv
+HXW7rwRiV9TdoNZZ946RvVM6l2LzUJyaK4wZZHf6WKJ2veL6LIrORA32vN+ofmpn
+XcTAUQ1JVyHbriy0GaT+1wYClqImWj8HxiskgpD+pKc+kzgl33xwwwqyuF1N7ikC
+AwEAAaNTMFEwHQYDVR0OBBYEFAK18YAZAaPQW7bHvqRwselDeGskMB8GA1UdIwQY
+MBaAFAK18YAZAaPQW7bHvqRwselDeGskMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
+hvcNAQELBQADgYEAgIvzyP0t4CjsmUmgG7QP977c3+Uvbt2wlCwe+rrXlqvuSeaW
+l4DaTyv8kYyiqIxgrTVI/G+HbpHgTO2yH57njTIAdRjsJgMU9z0oCazOtVD8KpXj
+SKFUtJVbY27BQAnbuDOawX96a0UDY44Ia9NaPuq0/mEcdCKSpQP4ZuvvKVc=
+-----END CERTIFICATE-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.key
new file mode 100644
index 000000000..354dbbdbb
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/pki/rsa_user.key
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMI29/1t8f2z1/m8
+pYdj4123BT8KXUzycKk8QnVIpyUSrx11u68EYlfU3aDWWfeOkb1TOpdi81CcmiuM
+GWR3+liidr3i+iyKzkQN9rzfqH5qZ13EwFENSVch264stBmk/tcGApaiJlo/B8Yr
+JIKQ/qSnPpM4Jd98cMMKsrhdTe4pAgMBAAECgYAX8c8BX9zF+rZWA/wkhRwzIa1z
+6EM4iWt6cgN/kkWJPJR6fVl2aoP1cDki60qMSveM8AX5RCnbdnNLiypWSLSEogdd
+bRWyFeF4ZXvivd+Lds2u5Ni3PiCrIpHfNvid2ERCaKhblQRdhi/dTH9Z+3kGspwc
+jpKzWMmGjBpqWjWOQQJBAOB3cS/AxbwJ6Fzvbi6sLiK6Ry8eSIMlce3Yyw89oU+M
+DGkIbggICCYKxXYIWtBbyxthdQudKFZYbLpCkLSMBXsCQQDdf5ICNN2R0ptYLhSX
+kQ4tiGigi1hq93+25Ov1rI8eIFSYlKNcyA/cvwv5ptlXmy1UAyoAdGCbS47pgCwT
+Nz+rAkEAtzHkR5PuDXSMluS2KRNPJ/qdxB/UEGzMGdEYkNy8vX5QVpyRqK5dcCbU
+V2ukKm7wSe11KEBgPnA2dKGFFkU85wJAD895Vpr7bdtAp2yyn5cFEg74mO0ZZJlC
+DoYMqb6lgJsCLtn9RzQonbMtYaadQPmcpLCNIPctpiggjV5OxxhcfQJBAM1ETm8p
+/9beBPTS8cJdWHvCRE149H/ZCUxqjFZriJzFYvi0xor85eK8/3V7xaWtTkK25i3+
+xWk+sA3DYYDPGM8=
+-----END PRIVATE KEY-----
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml
new file mode 100644
index 000000000..214f55fe2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/httpapi_connection.yml
@@ -0,0 +1,653 @@
+## Tests HTTTP Connection when a list of host are provided
+
+- 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) }}"
+ timeout: 5
+ output_level: debug
+
+- name: Set vars with the randomly generated list of hosts for the task level operations
+ ansible.builtin.set_fact:
+ last_host_active: "{{ aci_hostname | generate_random_ips(5,5) }}"
+ second_host_active: "{{aci_hostname|generate_random_ips(2,5)}}"
+ no_host_active: "{{aci_hostname|generate_random_ips(0,5)}}"
+
+- name: Set the actual connection type specified in the inventory (this var is used at the end of this test)
+ ansible.builtin.set_fact:
+ old_connection: "{{ ansible_connection }}"
+
+- name: Set the connection to httpapi and set session key used in the inventory
+ ansible.builtin.set_fact:
+ ansible_user: "{{ aci_username }}"
+ ansible_password: "{{ aci_password }}"
+ ansible_connection: ansible.netcommon.httpapi
+ ansible_httpapi_session_key: {'admin': "{{ lookup('file', 'pki/admin.key') }}"}
+ ansible_httpapi_validate_certs: "{{ aci_validate_certs | default(false) }}"
+ ansible_httpapi_use_ssl: "{{ aci_use_ssl | default(true) }}"
+ ansible_httpapi_use_proxy: "{{ aci_use_proxy | default(true) }}"
+ ansible_httpapi_port: 443
+ ansible_command_timeout: 5
+
+- name: Run aci_aaa_user_certificate through the plugin
+ include_tasks: ../../../../../../integration/targets/aci_aaa_user_certificate/tasks/main.yml
+
+- name: Add user certificate to be used later in the test
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ aaa_user: "{{ aci_username }}"
+ name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+
+# XML operation, APIC HTTP Error and Connection reset upon changed parameter tests
+- name: Add a tenant using an XML string (Check xml operations through plugin)
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: api/mo/uni.xml
+ method: post
+ content: '<fvTenant name="Sales" descr="Sales departement"/>'
+ register: tenant_xml_plugin
+
+- name: Add an AP (with non existent tenant)
+ cisco.aci.aci_ap:
+ <<: *aci_info
+ tenant: ansible_test_non_existent
+ ap: ap
+ description: default ap
+ state: present
+ ignore_errors: true
+ register: ap_non_existent_tenant
+
+- name: Delete Tenant with the wrong username and password (Check that connection resets)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ username: wrong_username
+ password: wrong_password
+ tenant: ansible_test
+ state: absent
+ ignore_errors: true
+ register: wrong_credentials
+
+- name: Set the username to null
+ ansible.builtin.set_fact:
+ ansible_user:
+
+- name: Delete Tenant with no username in the task or inventory (Check that username is set to the default value)
+ cisco.aci.aci_tenant:
+ host: "{{ aci_hostname }}"
+ password: "{{ aci_password }}"
+ validate_certs: "{{ aci_validate_certs | default(false) }}"
+ use_ssl: "{{ aci_use_ssl | default(true) }}"
+ use_proxy: "{{ aci_use_proxy | default(true) }}"
+ timeout: 5
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ ignore_errors: true
+ register: no_username
+
+- name: Revert the username to its original value
+ ansible.builtin.set_fact:
+ ansible_user: "{{ aci_username }}"
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ ap_non_existent_tenant_flattened: "{{ ap_non_existent_tenant.httpapi_logs | flatten }}"
+ wrong_credentials_flattened: "{{ wrong_credentials.httpapi_logs | flatten }}"
+ no_username_flattened: "{{ no_username.httpapi_logs | flatten }}"
+
+- name: Verify XML operation and HTTP error returned by APIC
+ assert:
+ that:
+ - tenant_xml_plugin.status == 200
+ - '"Received response from {{ aci_hostname }} for POST operation with HTTP: 400" in ap_non_existent_tenant_flattened'
+ - '"Re-setting connection due to change in the username" in wrong_credentials_flattened'
+ - '"Re-setting connection due to change in the password" in wrong_credentials_flattened'
+ - '"Connection to {{ aci_hostname }} has failed: HTTP Error 401: Unauthorized" in wrong_credentials_flattened'
+ - '"Establishing login for admin to {{ aci_hostname }}" in no_username_flattened'
+
+# Simulate HTTP 403 error test
+- name: Delete Tenant with only password in the task (Check for 403)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ tenant: ansible_test
+ state: absent
+ register: op17_task_pwd_delete_tenant
+
+- name: Add Tenant with only password in the task (Check for 403)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ tenant: ansible_test
+ state: present
+ register: op17_task_pwd_add_tenant
+
+- name: logout to render the token invalid
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ path: /api/aaaLogout.json
+ method: post
+ rsp_subtree_preserve: true
+ content: |
+ {
+ "aaaUser": {
+ "attributes": {
+ "name": "{{ aci_username }}"
+ }
+ }
+ }
+
+- name: Add an AP with only password in the task (Ensure re-login on the same host)
+ cisco.aci.aci_ap:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ tenant: ansible_test
+ ap: ap
+ description: default ap
+ state: present
+ register: op18_task_pwd_add_ap
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op18_flattened_task_pwd_add_ap: "{{ op18_task_pwd_add_ap.httpapi_logs | flatten }}"
+
+- name: Verify forbidden error 403
+ assert:
+ that:
+ - op17_task_pwd_add_tenant is changed
+ - op18_task_pwd_add_ap is changed
+ - '"Failed to receive response from {{ aci_hostname }} with HTTP Error 403: Forbidden" in op18_flattened_task_pwd_add_ap'
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" in op18_flattened_task_pwd_add_ap'
+ - '"Connection to {{ aci_hostname }} was successful" in op18_flattened_task_pwd_add_ap'
+
+- name: reset connection to test other scenarios
+ meta: reset_connection
+
+# Precedence test
+- name: Delete Tenant with password and private key in the task (private_key takes precedence)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: absent
+ register: op1_task_private_key_delete_tenant
+
+- name: Add Tenant with password and private key in the task (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: present
+ register: op1_task_private_key_add_tenant
+
+- name: Delete Tenant with only password in the task (password in the task takes precedence)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+ register: op2_task_pwd_delete_tenant
+
+- name: Add Tenant with only password in the task (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+ register: op2_task_pwd_add_tenant
+
+- name: Delete Tenant with password and session key in the inventory (session_key takes precedence)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op3_inventory_session_key_delete_tenant
+
+- name: Add Tenant with password and session key in the inventory (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: present
+ register: op3_inventory_session_key_add_tenant
+
+- name: Remove session key used in the inventory
+ ansible.builtin.set_fact:
+ ansible_httpapi_session_key:
+
+- name: Delete Tenant with with only password in the inventory (check for authentication with the password in the inventory)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op4_inventory_pwd_delete_tenant
+
+- name: Add Tenant with with only password in the inventory (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: present
+ register: op4_inventory_pwd_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op1_flattened_task_private_key_delete_tenant: "{{ op1_task_private_key_delete_tenant.httpapi_logs | flatten }}"
+ op1_flattened_task_private_key_add_tenant: "{{ op1_task_private_key_add_tenant.httpapi_logs | flatten }}"
+ op2_flattened_task_pwd_delete_tenant: "{{ op2_task_pwd_delete_tenant.httpapi_logs | flatten }}"
+ op2_flattened_task_pwd_add_tenant: "{{ op2_task_pwd_add_tenant.httpapi_logs | flatten }}"
+ op3_flattened_inventory_session_key_delete_tenant: "{{ op3_inventory_session_key_delete_tenant.httpapi_logs | flatten }}"
+ op3_flattened_inventory_session_key_add_tenant: "{{ op3_inventory_session_key_add_tenant.httpapi_logs | flatten }}"
+ op4_flattened_inventory_pwd_delete_tenant: "{{ op4_inventory_pwd_delete_tenant.httpapi_logs | flatten }}"
+ op4_flattened_inventory_pwd_add_tenant: "{{ op4_inventory_pwd_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify Precedence
+ assert:
+ that:
+ - '"Provided Hosts: [''{{ aci_hostname }}'']" in op1_flattened_task_private_key_delete_tenant'
+ - '"Initializing operation on {{ aci_hostname }}" in op1_flattened_task_private_key_delete_tenant'
+ - op1_task_private_key_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op1_flattened_task_private_key_add_tenant'
+ - op2_task_pwd_delete_tenant is changed
+ - '"Re-setting connection due to change from private/session key authentication to password authentication" in op2_flattened_task_pwd_delete_tenant'
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" in op2_flattened_task_pwd_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" in op2_flattened_task_pwd_delete_tenant'
+ - op2_task_pwd_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op2_flattened_task_pwd_add_tenant'
+ - op3_inventory_session_key_delete_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op3_flattened_inventory_session_key_delete_tenant'
+ - op3_inventory_session_key_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op3_flattened_inventory_session_key_add_tenant'
+ - op4_inventory_pwd_delete_tenant is changed
+ - '"Re-setting connection due to change from private/session key authentication to password authentication" in op4_flattened_inventory_pwd_delete_tenant'
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" in op4_flattened_inventory_pwd_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" in op4_flattened_inventory_pwd_delete_tenant'
+ - op4_inventory_pwd_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op4_flattened_inventory_pwd_add_tenant'
+
+- name: reset connection to test other scenarios
+ meta: reset_connection
+
+# Switching of hosts test with the password in the task
+- name: Delete Tenant with only password in the task (Check for successful operation on the last host)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ tenant: ansible_test
+ state: absent
+ register: op5_task_pwd_delete_tenant
+
+- name: Add Tenant with only password in the task (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ tenant: ansible_test
+ state: present
+ register: op5_task_pwd_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op5_flattened_task_pwd_delete_tenant: "{{ op5_task_pwd_delete_tenant.httpapi_logs | flatten }}"
+ op5_flattened_task_pwd_add_tenant: "{{ op5_task_pwd_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify switching of hosts with the password in the task
+ assert:
+ that:
+ - op5_task_pwd_delete_tenant is changed
+ - op5_flattened_task_pwd_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" in op5_flattened_task_pwd_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" in op5_flattened_task_pwd_delete_tenant'
+ - op5_task_pwd_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op5_flattened_task_pwd_add_tenant'
+
+# Continuing on the connected host test with the password in the task
+- name: Delete Tenant with only password in the task
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ second_host_active }}"
+ tenant: ansible_test
+ state: absent
+ register: op6_task_pwd_delete_tenant
+
+- name: Add Tenant with only password in the task (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ second_host_active }}"
+ tenant: ansible_test
+ state: present
+ register: op6_task_pwd_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op6_flattened_task_pwd_delete_tenant: "{{ op6_task_pwd_delete_tenant.httpapi_logs | flatten }}"
+ op6_flattened_task_pwd_add_tenant: "{{ op6_task_pwd_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify continuation of the operations on the connected host with the password in the task
+ assert:
+ that:
+ - op6_task_pwd_delete_tenant is changed
+ - '"Connected host {{ aci_hostname }} found in the provided hosts. Continuing with it." in op6_flattened_task_pwd_delete_tenant'
+ - op6_task_pwd_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op6_flattened_task_pwd_add_tenant'
+
+# Change of hosts and no hosts active test with the password in the task
+- name: Delete Tenant with only password in the task (Check for failed operation)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ no_host_active }}"
+ tenant: ansible_test
+ state: absent
+ register: op7_task_pwd_delete_tenant
+ ignore_errors: True
+
+- name: Add Tenant with only password in the task (Check the reset of the provided list of hosts)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ second_host_active }}"
+ tenant: ansible_test
+ state: present
+ register: op7_task_pwd_add_tenant
+
+- name: Verify failure when no hosts are active
+ assert:
+ that:
+ - op7_task_pwd_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none
+ - op7_task_pwd_add_tenant is not changed
+
+# Switching of hosts test with the the inventory password
+- name: Set list of hosts in the inventory with the last host as active
+ ansible.builtin.set_fact:
+ ansible_host: "{{aci_hostname|generate_random_ips(5,5)}}"
+
+- name: Delete Tenant with only password in the inventory (Check for successful operation on the last host)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op8_inventory_pwd_delete_tenant
+
+- name: Add Tenant with only password in the inventory (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: present
+ register: op8_inventory_pwd_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op8_flattened_inventory_pwd_delete_tenant: "{{ op8_inventory_pwd_delete_tenant.httpapi_logs | flatten }}"
+ op8_flattened_inventory_pwd_add_tenant: "{{ op8_inventory_pwd_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify switching of hosts with the password in the inventory
+ assert:
+ that:
+ - op8_inventory_pwd_delete_tenant is changed
+ - op8_flattened_inventory_pwd_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" in op8_flattened_inventory_pwd_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" in op8_flattened_inventory_pwd_delete_tenant'
+ - op8_inventory_pwd_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op8_flattened_inventory_pwd_add_tenant'
+
+# Continuing on the connected host test with the inventory password
+- name: Set list of hosts in the inventory with the second host as active
+ ansible.builtin.set_fact:
+ ansible_host: "{{aci_hostname|generate_random_ips(2,5)}}"
+
+- name: Delete Tenant with only password in the inventory (Check for execution on the previously connected host)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op9_inventory_pwd_delete_tenant
+
+- name: Add Tenant with only password in the inventory (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: present
+ register: op9_inventory_pwd_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op9_flattened_inventory_pwd_delete_tenant: "{{ op9_inventory_pwd_delete_tenant.httpapi_logs | flatten }}"
+ op9_flattened_inventory_pwd_add_tenant: "{{ op9_inventory_pwd_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify switching of hosts with the password in the inventory
+ assert:
+ that:
+ - op9_inventory_pwd_delete_tenant is changed
+ - op9_flattened_inventory_pwd_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" in op9_flattened_inventory_pwd_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" in op9_flattened_inventory_pwd_delete_tenant'
+ - op9_inventory_pwd_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op9_flattened_inventory_pwd_add_tenant'
+
+# Change of hosts and no hosts active test with the inventory password
+- name: Set list of hosts in the inventory with no active hosts
+ ansible.builtin.set_fact:
+ ansible_host: "{{aci_hostname|generate_random_ips(0,5)}}"
+
+- name: Delete Tenant with only password in the inventory (Check for failed operation)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op10_inventory_pwd_delete_tenant
+ ignore_errors: True
+
+- name: Verify failure when no hosts are active in the inventory
+ assert:
+ that:
+ - op10_inventory_pwd_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none
+
+# Switching of hosts test with the private key in the task
+- name: Delete Tenant with only private key in the task (Check for successful operation on the last host)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: absent
+ register: op11_task_private_key_delete_tenant
+
+- name: Add Tenant with only private key in the task (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ last_host_active }}"
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: present
+ register: op11_task_private_key_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op11_flattened_task_private_key_delete_tenant: "{{ op11_task_private_key_delete_tenant.httpapi_logs | flatten }}"
+ op11_flattened_task_private_key_add_tenant: "{{ op11_task_private_key_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify switching of hosts with the private key in the task
+ assert:
+ that:
+ - op11_task_private_key_delete_tenant is changed
+ - op11_flattened_task_private_key_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" not in op11_flattened_task_private_key_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" not in op11_flattened_task_private_key_delete_tenant'
+ - op11_task_private_key_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op11_flattened_task_private_key_add_tenant'
+
+# Continuing on the connected host test with the private key in the task
+- name: Delete Tenant with only private key in the task (Check for execution on the previously connected host)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ second_host_active }}"
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: absent
+ register: op12_task_private_key_delete_tenant
+
+- name: Add Tenant with only private key in the task (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ second_host_active }}"
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: present
+ register: op12_task_private_key_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op12_flattened_task_private_key_delete_tenant: "{{ op12_task_private_key_delete_tenant.httpapi_logs | flatten }}"
+ op12_flattened_task_private_key_add_tenant: "{{ op12_task_private_key_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify continuation of the operations on the connected host with the password in the task
+ assert:
+ that:
+ - op12_task_private_key_delete_tenant is changed
+ - '"Connected host {{ aci_hostname }} found in the provided hosts. Continuing with it." in op12_flattened_task_private_key_delete_tenant'
+ - op12_task_private_key_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op12_flattened_task_private_key_add_tenant'
+
+# Change of hosts and no hosts active test with the private key in the task
+- name: Delete Tenant with only private key in the task (Check for failed operation)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ no_host_active }}"
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: absent
+ register: op13_task_private_key_delete_tenant
+ ignore_errors: True
+
+- name: Add Tenant with only private key in the task (Check the reset of the provided list of hosts)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ host: "{{ second_host_active }}"
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ tenant: ansible_test
+ state: present
+ register: op13_task_private_key_add_tenant
+
+- name: Verify failure when no hosts are active in the task
+ assert:
+ that:
+ - op13_task_private_key_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none
+ - op13_task_private_key_add_tenant is not changed
+
+# Switching of hosts test with the the inventory session key
+- name: Set list of hosts in the inventory with the last host as active
+ ansible.builtin.set_fact:
+ ansible_host: "{{aci_hostname|generate_random_ips(5,5)}}"
+ ansible_httpapi_session_key: {'admin': "{{ lookup('file', 'pki/admin.key') }}"}
+
+- name: Delete Tenant with session key in the inventory (Check for successful operation on the last host)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op14_inventory_session_key_delete_tenant
+
+- name: Add Tenant with session key in the inventory (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: present
+ register: op14_inventory_session_key_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op14_flattened_inventory_session_key_delete_tenant: "{{ op14_inventory_session_key_delete_tenant.httpapi_logs | flatten }}"
+ op14_flattened_inventory_session_key_add_tenant: "{{ op14_inventory_session_key_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify switching of hosts with the session key in the inventory
+ assert:
+ that:
+ - op14_inventory_session_key_delete_tenant is changed
+ - op14_flattened_inventory_session_key_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" not in op14_flattened_inventory_session_key_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" not in op14_flattened_inventory_session_key_delete_tenant'
+ - op14_inventory_session_key_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op14_flattened_inventory_session_key_add_tenant'
+
+# Continuing on the connected host test with the inventory session key
+- name: Set list of hosts in the inventory with the second host as active
+ ansible.builtin.set_fact:
+ ansible_host: "{{aci_hostname|generate_random_ips(2,5)}}"
+
+- name: Delete Tenant with session key in the inventory (Check for execution on the previously connected host)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op15_inventory_session_key_delete_tenant
+
+- name: Add Tenant with session key in the inventory (Check for execution on the provided aci_hostname with no attempts at re-connection)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: present
+ register: op15_inventory_session_key_add_tenant
+
+- name: Flatten the registered instances
+ ansible.builtin.set_fact:
+ op15_flattened_inventory_session_key_delete_tenant: "{{ op15_inventory_session_key_delete_tenant.httpapi_logs | flatten }}"
+ op15_flattened_inventory_session_key_add_tenant: "{{ op15_inventory_session_key_add_tenant.httpapi_logs | flatten }}"
+
+- name: Verify switching of hosts with the session key in the inventory
+ assert:
+ that:
+ - op15_inventory_session_key_delete_tenant is changed
+ - op15_flattened_inventory_session_key_delete_tenant | regex_search('Switching host from [0-9]+(?:\.[0-9]+){3} to {{ aci_hostname }}') is not none
+ - '"Establishing login for {{ aci_username }} to {{ aci_hostname }}" not in op15_flattened_inventory_session_key_delete_tenant'
+ - '"Connection to {{ aci_hostname }} was successful" not in op15_flattened_inventory_session_key_delete_tenant'
+ - op15_inventory_session_key_add_tenant is changed
+ - '"Connection to {{ aci_hostname }} was successful" not in op15_flattened_inventory_session_key_add_tenant'
+
+# Change of hosts and no hosts active test with the inventory session key
+- name: Set list of hosts in the inventory with no active hosts
+ ansible.builtin.set_fact:
+ ansible_host: "{{aci_hostname|generate_random_ips(0,5)}}"
+
+- name: Delete Tenant with session key in the inventory (Check for failed operation)
+ cisco.aci.aci_tenant:
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+ register: op16_inventory_session_key_delete_tenant
+ ignore_errors: True
+
+- name: Verify failure when no hosts are active in the inventory
+ assert:
+ that:
+ - op16_inventory_session_key_delete_tenant.error.text | regex_search('No hosts left in the cluster to continue operation! Error on final host [0-9]+(?:\.[0-9]+){3}') is not none
+
+# Clean up Environment
+- name: Delete a tenant using an XML string
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: api/mo/uni/tn-[Sales].xml
+ method: delete
+ content: '<fvTenant name="Sales" descr="Sales departement"/>'
+
+- name: Remove user certificate
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *aci_info
+ aaa_user: "{{ aci_username }}"
+ name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: absent
+
+- name: Delete Tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ port: 443
+ tenant: ansible_test
+ state: absent
+
+- name: Cleanup facts to continue operation using the inventory file
+ ansible.builtin.set_fact:
+ ansible_host: "{{ aci_hostname }}"
+ ansible_connection: "{{ old_connection }}"
+ ansible_httpapi_session_key:
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml
index f3eba556e..b8a7a310f 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml
@@ -9,23 +9,26 @@
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
+- include_tasks: httpapi_connection.yml
+ tags: httpapi_connection
+
- name: Delete old log files to clean test directory
file:
path: "{{ item }}"
state: absent
with_items:
- - "{{ ansible_host }}_cm_add_tenant.json"
- - "{{ ansible_host }}_nm_add_tenant.json"
- - "{{ ansible_host }}_cm_add_tenant_again.json"
- - "{{ ansible_host }}_nm_add_tenant_again.json"
- - "{{ ansible_host }}_cm_add_tenant_descr.json"
- - "{{ ansible_host }}_nm_add_tenant_descr.json"
- - "{{ ansible_host }}_cm_add_tenant_descr_again.json"
- - "{{ ansible_host }}_nm_add_tenant_descr_again.json"
- - "{{ ansible_host }}_cm_remove_tenant.json"
- - "{{ ansible_host }}_nm_remove_tenant.json"
- - "{{ ansible_host }}_cm_remove_tenant_again.json"
- - "{{ ansible_host }}_nm_remove_tenant_again.json"
+ - "{{ aci_hostname }}_cm_add_tenant.json"
+ - "{{ aci_hostname }}_nm_add_tenant.json"
+ - "{{ aci_hostname }}_cm_add_tenant_again.json"
+ - "{{ aci_hostname }}_nm_add_tenant_again.json"
+ - "{{ aci_hostname }}_cm_add_tenant_descr.json"
+ - "{{ aci_hostname }}_nm_add_tenant_descr.json"
+ - "{{ aci_hostname }}_cm_add_tenant_descr_again.json"
+ - "{{ aci_hostname }}_nm_add_tenant_descr_again.json"
+ - "{{ aci_hostname }}_cm_remove_tenant.json"
+ - "{{ aci_hostname }}_nm_remove_tenant.json"
+ - "{{ aci_hostname }}_cm_remove_tenant_again.json"
+ - "{{ aci_hostname }}_nm_remove_tenant_again.json"
# CLEAN ENVIRONMENT
- name: Remove tenant
@@ -40,7 +43,6 @@
tenant: ansible_test
state: absent
-
# ADD TENANT
- name: Add tenant (check_mode)
cisco.aci.aci_tenant: &tenant_present
@@ -56,44 +58,44 @@
annotation: ansible_test
owner_key: ansible_key
owner_tag: ansible_tag
- output_path: "{{ ansible_host }}_cm_add_tenant.json"
+ output_path: "{{ aci_hostname }}_cm_add_tenant.json"
check_mode: true
register: cm_add_tenant
- name: Dump content of files
debug:
- msg: "{{ lookup('file', ansible_host +'_cm_add_tenant.json')}}"
+ msg: "{{ lookup('file', aci_hostname +'_cm_add_tenant.json')}}"
- name: Add tenant (normal mode)
cisco.aci.aci_tenant:
<<: *tenant_present
- output_path: "{{ ansible_host }}_nm_add_tenant.json"
+ output_path: "{{ aci_hostname }}_nm_add_tenant.json"
register: nm_add_tenant
- name: Add tenant again (check_mode)
cisco.aci.aci_tenant:
<<: *tenant_present
- output_path: "{{ ansible_host }}_cm_add_tenant_again.json"
+ output_path: "{{ aci_hostname }}_cm_add_tenant_again.json"
check_mode: true
register: cm_add_tenant_again
- name: Add tenant again (normal mode)
cisco.aci.aci_tenant:
<<: *tenant_present
- output_path: "{{ ansible_host }}_nm_add_tenant_again.json"
+ output_path: "{{ aci_hostname }}_nm_add_tenant_again.json"
register: nm_add_tenant_again
- name: Dump content of files
debug:
- msg: "{{ lookup('file', ansible_host + '_cm_add_tenant.json')}}"
+ msg: "{{ lookup('file', aci_hostname + '_cm_add_tenant.json')}}"
- name: Store file content on variables for create object
set_fact:
- fc_cm_add_tenant: "{{ lookup('file', ansible_host + '_cm_add_tenant.json') | from_json }}"
- fc_nm_add_tenant: "{{ lookup('file', ansible_host + '_nm_add_tenant.json') | from_json }}"
- fc_cm_add_tenant_again: "{{ lookup('file', ansible_host + '_cm_add_tenant_again.json') }}"
- fc_nm_add_tenant_again: "{{ lookup('file', ansible_host + '_nm_add_tenant_again.json') }}"
+ fc_cm_add_tenant: "{{ lookup('file', aci_hostname + '_cm_add_tenant.json') | from_json }}"
+ fc_nm_add_tenant: "{{ lookup('file', aci_hostname + '_nm_add_tenant.json') | from_json }}"
+ fc_cm_add_tenant_again: "{{ lookup('file', aci_hostname + '_cm_add_tenant_again.json') }}"
+ fc_nm_add_tenant_again: "{{ lookup('file', aci_hostname + '_nm_add_tenant_again.json') }}"
- name: Log file content verification for create object
assert:
@@ -119,7 +121,6 @@
- nm_add_tenant.current[0].fvTenant.attributes.ownerTag == 'ansible_tag'
- cm_add_tenant.proposed.fvTenant.attributes.ownerTag == 'ansible_tag'
-
# CHANGE TENANT
- name: Change description and annotation/owner_tag/owner_key of tenant (check_mode)
cisco.aci.aci_tenant:
@@ -128,7 +129,7 @@
annotation: ansible_test_changed
owner_key: ansible_key_changed
owner_tag: ansible_tag_changed
- output_path: "{{ ansible_host }}_cm_add_tenant_descr.json"
+ output_path: "{{ aci_hostname }}_cm_add_tenant_descr.json"
check_mode: true
register: cm_add_tenant_descr
@@ -139,7 +140,7 @@
annotation: ansible_test_changed
owner_key: ansible_key_changed
owner_tag: ansible_tag_changed
- output_path: "{{ ansible_host }}_nm_add_tenant_descr.json"
+ output_path: "{{ aci_hostname }}_nm_add_tenant_descr.json"
register: nm_add_tenant_descr
- name: Change description and annotation/owner_tag/owner_key of tenant again (check_mode)
@@ -149,7 +150,7 @@
annotation: ansible_test_changed
owner_key: ansible_key_changed
owner_tag: ansible_tag_changed
- output_path: "{{ ansible_host }}_cm_add_tenant_descr_again.json"
+ output_path: "{{ aci_hostname }}_cm_add_tenant_descr_again.json"
check_mode: true
register: cm_add_tenant_descr_again
@@ -160,15 +161,15 @@
annotation: ansible_test_changed
owner_key: ansible_key_changed
owner_tag: ansible_tag_changed
- output_path: "{{ ansible_host }}_nm_add_tenant_descr_again.json"
+ output_path: "{{ aci_hostname }}_nm_add_tenant_descr_again.json"
register: nm_add_tenant_descr_again
- name: Store file content on variables for update object
set_fact:
- fc_cm_add_tenant_descr: "{{ lookup('file', ansible_host + '_cm_add_tenant_descr.json') | from_json }}"
- fc_nm_add_tenant_descr: "{{ lookup('file', ansible_host + '_nm_add_tenant_descr.json') | from_json }}"
- fc_cm_add_tenant_descr_again: "{{ lookup('file', ansible_host + '_cm_add_tenant_descr_again.json') }}"
- fc_nm_add_tenant_descr_again: "{{ lookup('file', ansible_host + '_nm_add_tenant_descr_again.json') }}"
+ fc_cm_add_tenant_descr: "{{ lookup('file', aci_hostname + '_cm_add_tenant_descr.json') | from_json }}"
+ fc_nm_add_tenant_descr: "{{ lookup('file', aci_hostname + '_nm_add_tenant_descr.json') | from_json }}"
+ fc_cm_add_tenant_descr_again: "{{ lookup('file', aci_hostname + '_cm_add_tenant_descr_again.json') }}"
+ fc_nm_add_tenant_descr_again: "{{ lookup('file', aci_hostname + '_nm_add_tenant_descr_again.json') }}"
- name: Log file content verification for update object
assert:
@@ -295,35 +296,35 @@
- name: Remove tenant (check_mode)
cisco.aci.aci_tenant:
<<: *tenant_absent
- output_path: "{{ ansible_host }}_cm_remove_tenant.json"
+ output_path: "{{ aci_hostname }}_cm_remove_tenant.json"
check_mode: true
register: cm_remove_tenant
- name: Remove tenant (normal mode)
cisco.aci.aci_tenant:
<<: *tenant_absent
- output_path: "{{ ansible_host }}_nm_remove_tenant.json"
+ output_path: "{{ aci_hostname }}_nm_remove_tenant.json"
register: nm_remove_tenant
- name: Remove tenant again (check_mode)
cisco.aci.aci_tenant:
<<: *tenant_absent
- output_path: "{{ ansible_host }}_cm_remove_tenant_again.json"
+ output_path: "{{ aci_hostname }}_cm_remove_tenant_again.json"
check_mode: true
register: cm_remove_tenant_again
- name: Remove tenant again (normal mode)
cisco.aci.aci_tenant:
<<: *tenant_absent
- output_path: "{{ ansible_host }}_nm_remove_tenant_again.json"
+ output_path: "{{ aci_hostname }}_nm_remove_tenant_again.json"
register: nm_remove_tenant_again
- name: Store file content on variables for delete object
set_fact:
- fc_cm_remove_tenant: "{{ lookup('file', ansible_host + '_cm_remove_tenant.json') | from_json }}"
- fc_nm_remove_tenant: "{{ lookup('file', ansible_host + '_nm_remove_tenant.json') | from_json }}"
- fc_cm_remove_tenant_again: "{{ lookup('file', ansible_host + '_cm_remove_tenant_again.json') }}"
- fc_nm_remove_tenant_again: "{{ lookup('file', ansible_host + '_nm_remove_tenant_again.json') }}"
+ fc_cm_remove_tenant: "{{ lookup('file', aci_hostname + '_cm_remove_tenant.json') | from_json }}"
+ fc_nm_remove_tenant: "{{ lookup('file', aci_hostname + '_nm_remove_tenant.json') | from_json }}"
+ fc_cm_remove_tenant_again: "{{ lookup('file', aci_hostname + '_cm_remove_tenant_again.json') }}"
+ fc_nm_remove_tenant_again: "{{ lookup('file', aci_hostname + '_nm_remove_tenant_again.json') }}"
- name: Log file content verification for delete object
assert:
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml
new file mode 100644
index 000000000..b993b0e33
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_action_rule_profile/tasks/main.yml
@@ -0,0 +1,146 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: create tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+
+ - name: Ensure first action rule profile does not exist
+ aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_absent
+ <<: *aci_tenant_present
+ name: anstest
+ description: test for action rule profile
+ state: absent
+
+ - name: Ensure second action rule profile does not exist
+ aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_absent
+ <<: *aci_tenant_present
+ name: anstest_2
+ state: absent
+
+ - name: Create first action rule profile (check_mode)
+ aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_present
+ <<: *aci_tenant_action_rule_profile_absent
+ state: present
+ check_mode: true
+ register: cm_add_tenant_action_rule_profile_1
+
+ - name: Create first action rule profile (normal_mode)
+ aci_tenant_action_rule_profile:
+ <<: *aci_tenant_action_rule_profile_present
+ register: nm_add_tenant_action_rule_profile_1
+
+ - name: Create first action rule profile again - testing idempotency
+ aci_tenant_action_rule_profile:
+ <<: *aci_tenant_action_rule_profile_present
+ register: idempotency_add_tenant_action_rule_profile_1
+
+ - name: Create second action rule profile
+ aci_tenant_action_rule_profile: &aci_tenant_action_rule_profile_2_present
+ <<: *aci_tenant_action_rule_profile_2_absent
+ state: present
+ register: nm_add_tenant_action_rule_profile_2
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_tenant_action_rule_profile_1 is changed
+ - cm_add_tenant_action_rule_profile_1.previous == []
+ - cm_add_tenant_action_rule_profile_1.current == []
+ - nm_add_tenant_action_rule_profile_1 is changed
+ - nm_add_tenant_action_rule_profile_1.current.0.rtctrlAttrP.attributes.name == "anstest"
+ - idempotency_add_tenant_action_rule_profile_1 is not changed
+ - nm_add_tenant_action_rule_profile_2 is changed
+ - nm_add_tenant_action_rule_profile_2.current.0.rtctrlAttrP.attributes.name == "anstest_2"
+
+ - name: Query all action rule profiles
+ aci_tenant_action_rule_profile:
+ <<: *aci_info
+ state: query
+ register: query_all_tenant_action_rule_profile
+
+ - name: Query first action rule profile
+ aci_tenant_action_rule_profile:
+ <<: *aci_tenant_action_rule_profile_present
+ state: query
+ register: query_first_tenant_action_rule_profile
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_tenant_action_rule_profile is not changed
+ - query_all_tenant_action_rule_profile.current | length >= 2
+ - '"class/rtctrlAttrP.json" in query_all_tenant_action_rule_profile.url'
+ - query_first_tenant_action_rule_profile is not changed
+ - query_first_tenant_action_rule_profile.current.0.rtctrlAttrP.attributes.name == "anstest"
+
+ - name: Delete first action rule profile (check_mode)
+ aci_tenant_action_rule_profile:
+ <<: *aci_tenant_action_rule_profile_present
+ state: absent
+ check_mode: true
+ register: cm_delete_tenant_action_rule_profile_1
+
+ - name: Delete first action rule profile (normal_mode)
+ aci_tenant_action_rule_profile:
+ <<: *aci_tenant_action_rule_profile_present
+ state: absent
+ register: nm_delete_tenant_action_rule_profile_1
+
+ - name: Delete first action rule profile again - testing idempotency
+ aci_tenant_action_rule_profile:
+ <<: *aci_tenant_action_rule_profile_present
+ state: absent
+ register: idempotency_delete_tenant_action_rule_profile_1
+
+ - name: Delete second action rule profile (normal_mode)
+ aci_tenant_action_rule_profile:
+ <<: *aci_tenant_action_rule_profile_2_present
+ state: absent
+ register: nm_delete_tenant_action_rule_profile_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_tenant_action_rule_profile_1 is changed
+ - cm_delete_tenant_action_rule_profile_1.proposed == {}
+ - nm_delete_tenant_action_rule_profile_1 is changed
+ - nm_delete_tenant_action_rule_profile_1.previous != []
+ - nm_delete_tenant_action_rule_profile_1.current == []
+ - idempotency_delete_tenant_action_rule_profile_1 is not changed
+ - idempotency_delete_tenant_action_rule_profile_1.previous == []
+ - nm_delete_tenant_action_rule_profile_2 is changed
+ - nm_delete_tenant_action_rule_profile_2.previous != []
+ - nm_delete_tenant_action_rule_profile_2.current == []
+
+ - name: Delete tenant - clean up the environment
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml
new file mode 100644
index 000000000..96ba34077
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_ep_retention_policy/tasks/main.yml
@@ -0,0 +1,214 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Gaspard Micol (@gmicol) <gmicol@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+
+- 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
+ # Clean Environment
+ - name: create tenant
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+
+ - name: Ensure first EP retention protocol policy does not exist
+ aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_absent
+ <<: *aci_tenant_present
+ name: ep_policy_anstest
+ description: test for EP retention protocol policy
+ bounce_age: 300
+ bounce_trigger: flood
+ hold_interval: 600
+ local_ep_interval: 1800
+ remote_ep_interval: 600
+ move_frequency: 512
+ state: absent
+
+ - name: Ensure second EP retention protocol policy does not exist
+ aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_2_absent
+ <<: *aci_tenant_present
+ name: ep_policy_anstest_2
+ bounce_age: 0
+ local_ep_interval: 0
+ remote_ep_interval: 0
+ move_frequency: 0
+ state: absent
+
+ - name: Create first EP retention protocol policy (check_mode)
+ aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_present
+ <<: *aci_tenant_ep_retention_policy_absent
+ state: present
+ check_mode: true
+ register: cm_add_tenant_ep_retention_policy_1
+
+ - name: Create first EP retention protocol policy (normal_mode)
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ register: nm_add_tenant_ep_retention_policy_1
+
+ - name: Create first EP retention protocol policy again - testing idempotency
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ register: idempotency_add_tenant_ep_retention_policy_1
+
+ - name: Create second EP retention protocol policy
+ aci_tenant_ep_retention_policy: &aci_tenant_ep_retention_policy_2_present
+ <<: *aci_tenant_ep_retention_policy_2_absent
+ state: present
+ register: nm_add_tenant_ep_retention_policy_2
+
+ - name: Modify EP retention protocol policy bounce age - testing failure message
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ bounce_age: 100
+ ignore_errors: true
+ register: Modify_tenant_ep_retention_policy_bounce_age
+
+ - name: Modify EP retention protocol policy hold interval - testing failure message
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ hold_interval: 4
+ ignore_errors: true
+ register: Modify_tenant_ep_retention_policy_hold_interval
+
+ - name: Modify EP retention protocol policy move frequency - testing failure message
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ move_frequency: 65540
+ ignore_errors: true
+ register: Modify_tenant_ep_retention_policy_move_frequency
+
+ - name: Modify EP retention protocol policy local ep interval - testing failure message
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ local_ep_interval: 119
+ ignore_errors: true
+ register: Modify_tenant_ep_retention_policy_local_ep_interval
+
+ - name: Modify EP retention protocol policy remote ep interval - testing failure message
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ remote_ep_interval: 119
+ ignore_errors: true
+ register: Modify_tenant_ep_retention_policy_remote_ep_interval
+
+ - name: Asserts for creation tasks
+ assert:
+ that:
+ - cm_add_tenant_ep_retention_policy_1 is changed
+ - cm_add_tenant_ep_retention_policy_1.previous == []
+ - cm_add_tenant_ep_retention_policy_1.current == []
+ - nm_add_tenant_ep_retention_policy_1 is changed
+ - nm_add_tenant_ep_retention_policy_1.current.0.fvEpRetPol.attributes.name == "ep_policy_anstest"
+ - nm_add_tenant_ep_retention_policy_1.current.0.fvEpRetPol.attributes.bounceAgeIntvl == "300"
+ - nm_add_tenant_ep_retention_policy_1.current.0.fvEpRetPol.attributes.bounceTrig == "rarp-flood"
+ - nm_add_tenant_ep_retention_policy_1.current.0.fvEpRetPol.attributes.holdIntvl == "600"
+ - nm_add_tenant_ep_retention_policy_1.current.0.fvEpRetPol.attributes.localEpAgeIntvl == "1800"
+ - nm_add_tenant_ep_retention_policy_1.current.0.fvEpRetPol.attributes.moveFreq == "512"
+ - nm_add_tenant_ep_retention_policy_1.current.0.fvEpRetPol.attributes.remoteEpAgeIntvl == "600"
+ - idempotency_add_tenant_ep_retention_policy_1 is not changed
+ - nm_add_tenant_ep_retention_policy_2 is changed
+ - nm_add_tenant_ep_retention_policy_2.current.0.fvEpRetPol.attributes.bounceAgeIntvl == "infinite"
+ - nm_add_tenant_ep_retention_policy_2.current.0.fvEpRetPol.attributes.bounceTrig == "protocol"
+ - nm_add_tenant_ep_retention_policy_2.current.0.fvEpRetPol.attributes.holdIntvl == "300"
+ - nm_add_tenant_ep_retention_policy_2.current.0.fvEpRetPol.attributes.localEpAgeIntvl == "infinite"
+ - nm_add_tenant_ep_retention_policy_2.current.0.fvEpRetPol.attributes.moveFreq == "none"
+ - nm_add_tenant_ep_retention_policy_2.current.0.fvEpRetPol.attributes.remoteEpAgeIntvl == "infinite"
+ - nm_add_tenant_ep_retention_policy_2.current.0.fvEpRetPol.attributes.name == "ep_policy_anstest_2"
+ - Modify_tenant_ep_retention_policy_bounce_age.msg == "The bounce_age must be a value of 0 or between 150 and 65535"
+ - Modify_tenant_ep_retention_policy_hold_interval.msg == "The hold_interval must be a value between 5 and 65535"
+ - Modify_tenant_ep_retention_policy_move_frequency.msg == "The move_frequency must be a value between 0 and 65535"
+ - Modify_tenant_ep_retention_policy_local_ep_interval.msg == "The local_ep_interval must be a value of 0 or between 120 and 65535"
+ - Modify_tenant_ep_retention_policy_remote_ep_interval.msg == "The remote_ep_interval must be a value of 0 or between 120 and 65535"
+
+ - name: Query all EP retention protocol policies
+ aci_tenant_ep_retention_policy:
+ <<: *aci_info
+ state: query
+ register: query_all_tenant_ep_retention_policy
+
+ - name: Query first EP retention protocol policy
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ state: query
+ register: query_first_tenant_ep_retention_policy
+
+ - name: Asserts for query tasks
+ assert:
+ that:
+ - query_all_tenant_ep_retention_policy is not changed
+ - query_all_tenant_ep_retention_policy.current | length >= 2
+ - '"class/fvEpRetPol.json" in query_all_tenant_ep_retention_policy.url'
+ - query_first_tenant_ep_retention_policy is not changed
+ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.name == "ep_policy_anstest"
+ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.bounceAgeIntvl == "300"
+ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.bounceTrig == "rarp-flood"
+ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.holdIntvl == "600"
+ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.localEpAgeIntvl == "1800"
+ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.moveFreq == "512"
+ - query_first_tenant_ep_retention_policy.current.0.fvEpRetPol.attributes.remoteEpAgeIntvl == "600"
+
+ - name: Delete first EP retention protocol policy (check_mode)
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ state: absent
+ check_mode: true
+ register: cm_delete_tenant_ep_retention_policy_1
+
+ - name: Delete first EP retention protocol policy (normal_mode)
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ state: absent
+ register: nm_delete_tenant_ep_retention_policy_1
+
+ - name: Delete first EP retention protocol policy again - testing idempotency
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_present
+ state: absent
+ register: idempotency_delete_tenant_ep_retention_policy_1
+
+ - name: Delete second EP retention protocol policy (normal_mode)
+ aci_tenant_ep_retention_policy:
+ <<: *aci_tenant_ep_retention_policy_2_present
+ state: absent
+ register: nm_delete_tenant_ep_retention_policy_2
+
+ - name: Asserts for deletion tasks
+ assert:
+ that:
+ - cm_delete_tenant_ep_retention_policy_1 is changed
+ - cm_delete_tenant_ep_retention_policy_1.proposed == {}
+ - nm_delete_tenant_ep_retention_policy_1 is changed
+ - nm_delete_tenant_ep_retention_policy_1.previous != []
+ - nm_delete_tenant_ep_retention_policy_1.current == []
+ - idempotency_delete_tenant_ep_retention_policy_1 is not changed
+ - idempotency_delete_tenant_ep_retention_policy_1.previous == []
+ - nm_delete_tenant_ep_retention_policy_2 is changed
+ - nm_delete_tenant_ep_retention_policy_2.previous != []
+ - nm_delete_tenant_ep_retention_policy_2.current == []
+
+ - name: Delete tenant - clean up the environment
+ aci_tenant:
+ <<: *aci_tenant_present
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml
index d7d807ad8..543a25cd5 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml
@@ -26,216 +26,230 @@
tenant: ansible_tenant
state: absent
-- name: Add a new tenant
- aci_tenant:
- <<: *aci_info
- tenant: ansible_tenant
- description: Ansible tenant
- state: present
-
-- name: Add span ansible_group
- aci_tenant_span_dst_group:
- <<: *aci_info
- destination_group: ansible_group
- description: Test span
- destination_ip: 10.0.0.1
- source_ip: 10.0.2.1
- tenant: ansible_tenant
- destination_epg:
- tenant: Test1
- ap: ap1
- epg: ep1
- version_enforced: false
- span_version: version_1
- ttl: 2
- mtu: 1500
- flow_id: 1
- dscp: "CS1"
- state: present
- register: add_span1
-
-- name: Verify add span
- assert:
- that:
- - add_span1 is changed
- - add_span1.current.0.spanDestGrp.attributes.name == "ansible_group"
- - add_span1.current.0.spanDestGrp.attributes.descr == "Test span"
- - add_span1.current.0.spanDestGrp.attributes.dn == "uni/tn-ansible_tenant/destgrp-ansible_group"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "CS1"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver1"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "no"
- - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "2"
- - add_span1.current.0.spanDestGrp.attributes.annotation == 'orchestrator:ansible'
-
-- name: Add span ansible_group again
- aci_tenant_span_dst_group:
- <<: *aci_info
- destination_group: ansible_group
- description: Test span
- destination_ip: 10.0.0.1
- source_ip: 10.0.2.1
- tenant: ansible_tenant
- destination_epg:
- tenant: Test1
- ap: ap1
- epg: ep1
- version_enforced: false
- span_version: version_1
- ttl: 2
- mtu: 1500
- flow_id: 1
- dscp: "CS1"
- state: present
- register: add_span1_again
-
-- name: Verify add span again
- assert:
- that:
- - add_span1_again is not changed
-
-- name: Change span ansible_group's src ip
- aci_tenant_span_dst_group:
- <<: *aci_info
- destination_group: ansible_group2
- description: Test span
- destination_ip: 10.0.0.2
- source_ip: 10.0.2.1
- tenant: ansible_tenant
- destination_epg:
- tenant: Test1
- ap: ap1
- epg: ep1
- version_enforced: false
- span_version: version_1
- ttl: 2
- mtu: 1500
- flow_id: 1
- dscp: CS1
- state: present
- register: change_span1_ip
-
-- name: Change span ansible_group's dscp
- aci_tenant_span_dst_group:
- <<: *aci_info
- destination_group: ansible_group2
- description: Test span
- destination_ip: 10.0.0.2
- source_ip: 10.0.2.1
- tenant: ansible_tenant
- destination_epg:
- tenant: Test1
- ap: ap1
- epg: ep1
- version_enforced: false
- span_version: version_1
- ttl: 2
- mtu: 1500
- flow_id: 1
- dscp: VA
- state: present
- register: change_span1_dscp
-
-- name: Verify changes in span
- assert:
- that:
- - change_span1_ip.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.2"
- - change_span1_dscp.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "VA"
-
-- name: Add span ansible_group2
- aci_tenant_span_dst_group:
- <<: *aci_info
- destination_group: ansible_group2
- description: Test span
- destination_ip: 10.0.0.1
- source_ip: 10.0.2.1
- tenant: ansible_tenant
- destination_epg:
- tenant: Test1
- ap: ap1
- epg: ep1
- version_enforced: true
- span_version: version_2
- ttl: 2
- mtu: 1500
- flow_id: 1
- dscp: CS1
- state: present
- register: add_span2
-
-- name: Verify addition of second span
- assert:
- that:
- - add_span2 is changed
- - add_span2.current.0.spanDestGrp.attributes.name == "ansible_group2"
- - add_span2.current.0.spanDestGrp.attributes.descr == "Test span"
- - add_span2.current.0.spanDestGrp.attributes.dn == "uni/tn-ansible_tenant/destgrp-ansible_group2"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group2"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "CS1"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver2"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "yes"
- - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "2"
-
-- name: Query span ansible_group
- aci_tenant_span_dst_group:
- <<: *aci_info
- tenant: ansible_tenant
- destination_group: ansible_group
- state: query
- register: query_span_ansible_group
-
-- name: Query all span dest groups
- aci_tenant_span_dst_group:
- <<: *aci_info
- state: query
- register: query_all_span
-
-- name: Verify Query of span
- assert:
- that:
- - query_span_ansible_group is not changed
- - query_span_ansible_group.current.0.spanDestGrp.attributes.name == "ansible_group"
- - query_span_ansible_group.current.0.spanDestGrp.attributes.descr == "Test span"
- - query_span_ansible_group.current.0.spanDestGrp.attributes.dn == "uni/tn-ansible_tenant/destgrp-ansible_group"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "CS1"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "no"
- - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "2"
- - query_all_span is not changed
- - query_all_span | length >= 2
-
-- name: Remove span ansible_group
- aci_tenant_span_dst_group:
- <<: *aci_info
- tenant: ansible_tenant
- destination_group: ansible_group
- state: absent
- register: remove_span1
-
-- name: Remove span ansible_group2
- aci_tenant_span_dst_group:
- <<: *aci_info
- tenant: ansible_tenant
- destination_group: ansible_group2
- state: absent
- register: remove_span2
-
-- name: Verify Remove of span
- assert:
- that:
- - remove_span1 is changed
- - remove_span1.current == []
- - remove_span2 is changed
- - remove_span2.current == []
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+
+ - name: Add a new tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ - name: Add span ansible_group
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_group
+ description: Test span
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ destination_epg:
+ tenant: Test1
+ ap: ap1
+ epg: ep1
+ version_enforced: false
+ span_version: version_1
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: "CS1"
+ state: present
+ register: add_span1
+
+ - name: Verify add span
+ assert:
+ that:
+ - add_span1 is changed
+ - add_span1.current.0.spanDestGrp.attributes.name == "ansible_group"
+ - add_span1.current.0.spanDestGrp.attributes.descr == "Test span"
+ - add_span1.current.0.spanDestGrp.attributes.dn == "uni/tn-ansible_tenant/destgrp-ansible_group"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "CS1"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver1"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "no"
+ - add_span1.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "2"
+ - add_span1.current.0.spanDestGrp.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add span ansible_group again
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_group
+ description: Test span
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ destination_epg:
+ tenant: Test1
+ ap: ap1
+ epg: ep1
+ version_enforced: false
+ span_version: version_1
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: "CS1"
+ state: present
+ register: add_span1_again
+
+ - name: Verify add span again
+ assert:
+ that:
+ - add_span1_again is not changed
+
+ - name: Change span ansible_group's src ip
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_group2
+ description: Test span
+ destination_ip: 10.0.0.2
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ destination_epg:
+ tenant: Test1
+ ap: ap1
+ epg: ep1
+ version_enforced: false
+ span_version: version_1
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: CS1
+ state: present
+ register: change_span1_ip
+
+ - name: Change span ansible_group's dscp
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_group2
+ description: Test span
+ destination_ip: 10.0.0.2
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ destination_epg:
+ tenant: Test1
+ ap: ap1
+ epg: ep1
+ version_enforced: false
+ span_version: version_1
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: VA
+ state: present
+ register: change_span1_dscp
+
+ - name: Verify changes in span
+ assert:
+ that:
+ - change_span1_ip.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.2"
+ - change_span1_dscp.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "VA"
+
+ - name: Add span ansible_group2
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_group2
+ description: Test span
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ destination_epg:
+ tenant: Test1
+ ap: ap1
+ epg: ep1
+ version_enforced: true
+ span_version: version_2
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: CS1
+ state: present
+ register: add_span2
+
+ - name: Verify addition of second span
+ assert:
+ that:
+ - add_span2 is changed
+ - add_span2.current.0.spanDestGrp.attributes.name == "ansible_group2"
+ - add_span2.current.0.spanDestGrp.attributes.descr == "Test span"
+ - add_span2.current.0.spanDestGrp.attributes.dn == "uni/tn-ansible_tenant/destgrp-ansible_group2"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group2"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "CS1"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ver == "ver2"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "yes"
+ - add_span2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "2"
+
+ - name: Query span ansible_group
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ tenant: ansible_tenant
+ destination_group: ansible_group
+ state: query
+ register: query_span_ansible_group
+
+ - name: Query all span dest groups
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_all_span
+
+ - name: Verify Query of span
+ assert:
+ that:
+ - query_span_ansible_group is not changed
+ - query_span_ansible_group.current.0.spanDestGrp.attributes.name == "ansible_group"
+ - query_span_ansible_group.current.0.spanDestGrp.attributes.descr == "Test span"
+ - query_span_ansible_group.current.0.spanDestGrp.attributes.dn == "uni/tn-ansible_tenant/destgrp-ansible_group"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.dscp == "CS1"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.srcIpPrefix == "10.0.2.1"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ip == "10.0.0.1"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.mtu == "1500"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.flowId == "1"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.verEnforced == "no"
+ - query_span_ansible_group.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestEpg.attributes.ttl == "2"
+ - query_all_span is not changed
+ - query_all_span | length >= 2
+
+ - name: Remove span ansible_group
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ tenant: ansible_tenant
+ destination_group: ansible_group
+ state: absent
+ register: remove_span1
+
+ - name: Remove span ansible_group2
+ aci_tenant_span_dst_group:
+ <<: *aci_info
+ tenant: ansible_tenant
+ destination_group: ansible_group2
+ state: absent
+ register: remove_span2
+
+ - name: Verify Remove of span
+ assert:
+ that:
+ - remove_span1 is changed
+ - remove_span1.current == []
+ - remove_span2 is changed
+ - remove_span2.current == []
+
+ # CLEAN ENVIRONMENT
+ - name: Remove the ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml
index c39259593..5ccf8bfbf 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml
@@ -215,6 +215,7 @@
cisco.aci.aci_vlan_pool_encap_block: &aci_encap_block_query_filter
<<: *aci_encap_block_query
pool: "{{ fake_var | default(omit) }}"
+ pool_allocation_mode: "{{ fake_var | default(omit) }}"
register: encap_block_query_from_to_name
- name: Query assertions
@@ -313,6 +314,7 @@
<<: *aci_pool_present
state: query
pool: "{{ fake_var | default(omit) }}"
+ pool_allocation_mode: "{{ fake_var | default(omit) }}"
register: encap_block_query_all
- name: Query assertions
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml
index fa3f1057c..695f40fe7 100644
--- a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml
@@ -62,6 +62,7 @@
policy_control_direction: egress
preferred_group: enabled
match_type: all
+ ip_data_plane_learning: disabled
register: vrf_present_2
- name: create vrf without all necessary params - failure message works
@@ -80,6 +81,7 @@
- vrf_present is changed
- vrf_present.sent == vrf_present_check_mode.sent
- vrf_present.current.0.fvCtx.attributes.annotation == 'orchestrator:ansible'
+ - vrf_present.current.0.fvCtx.attributes.ipDataPlaneLearning == 'enabled'
- vrf_present.previous == []
- vrf_present_idempotent is not changed
- vrf_present_idempotent.previous != []
@@ -88,9 +90,11 @@
- vrf_update.sent != vrf_update.proposed
- vrf_update.sent.fvCtx.attributes.descr == 'Ansible Test Update'
- vrf_update.sent.fvCtx.attributes.pcEnfPref == 'unenforced'
+ - vrf_update.current.0.fvCtx.attributes.ipDataPlaneLearning == 'enabled'
- vrf_present_2.sent.fvCtx.attributes.name == 'anstest2'
- vrf_present_2.sent.fvCtx.attributes.pcEnfDir == 'egress'
- vrf_present_2.sent.fvCtx.attributes.descr == 'Ansible Test'
+ - vrf_present_2.current.0.fvCtx.attributes.ipDataPlaneLearning == 'disabled'
- vrf_present_2.current.0.fvCtx.children.0.vzAny.attributes.matchT == 'All'
- vrf_present_2.current.0.fvCtx.children.0.vzAny.attributes.prefGrMemb == 'enabled'
- vrf_present_missing_param is failed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/aliases
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/aliases
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml
new file mode 100644
index 000000000..2455f24e4
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml
@@ -0,0 +1,233 @@
+# 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: 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_to:
+ - 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_to:
+ - 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_to:
+ - vrf: "test"
+ tenant: "ansible_test3"
+ description: Ansible Test
+ 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:
+ - vrf_present is changed
+ - leak_sub_check_mode is changed
+ - 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.leakInternalSubnet.attributes.ip == '1.1.1.2'
+ - 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'
+ - 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
+ <<: *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_to:
+ - vrf: "test"
+ tenant: "ansible_test3"
+ description: Ansible Test
+ ip: 1.1.1.2
+ 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'
+ - 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'
+ - 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 - 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: &aci_delete_again
+ <<: *aci_vrf_present
+ vrf: test
+ leak_to:
+ - vrf: "test2"
+ tenant: "ansible_test3"
+ 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_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'
+ - leak_sub_delete.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3'
+ - 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'
+ - 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