summaryrefslogtreecommitdiffstats
path: root/ansible_collections/cisco/aci/tests/integration
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/cisco/aci/tests/integration
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/cisco/aci/tests/integration')
-rw-r--r--ansible_collections/cisco/aci/tests/integration/inventory.networking13
-rw-r--r--ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt12
-rw-r--r--ansible_collections/cisco/aci/tests/integration/target-prefixes.network1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml237
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml227
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml229
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/pki/sshkey.pub1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml164
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml236
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt14
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin_invalid.key3
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/openssh_rsa.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key15
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt14
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml346
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml224
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml336
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml261
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml728
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/tasks/main.yml347
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/tasks/main.yml154
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml274
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml148
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml338
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml223
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml235
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_ap/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml202
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml312
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml154
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml247
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml87
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/tasks/main.yml132
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml772
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml157
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml133
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml123
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml310
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml255
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml185
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml232
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml191
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml182
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml56
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml74
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml261
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml114
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml97
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/tasks/main.yml161
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml110
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml148
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml165
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml140
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml400
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml379
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml159
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml161
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml570
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml169
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/tasks/main.yml107
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml169
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml299
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml248
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml249
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml24
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml248
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml217
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml655
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml228
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml24
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml275
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vsan.yml16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml179
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml24
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml388
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml20
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml19
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml316
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml265
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml196
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml209
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml735
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml306
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml218
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/tasks/main.yml250
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml181
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml188
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml122
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml194
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml218
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml264
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml122
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml194
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/tasks/main.yml268
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml344
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml224
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml315
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml208
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml239
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml464
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml680
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml289
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml111
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml169
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml460
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml273
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml295
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml292
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml232
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml177
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/aliases1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml162
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml181
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml136
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml163
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml218
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml202
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml160
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml190
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml1516
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml152
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml318
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml535
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml502
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml174
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml172
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml149
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml155
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml222
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml258
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml149
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml148
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml251
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml209
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml237
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml230
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml166
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml157
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml31
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/pki/admin.crt14
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/pki/admin.key16
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml214
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_negative_update_check.xml1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml1
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml167
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml148
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml148
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml160
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/tasks/main.yml162
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/tasks/main.yml136
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/tasks/main.yml135
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/tasks/main.yml111
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml391
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml322
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml149
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml219
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml214
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/tasks/main.yml245
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml197
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml168
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml63
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml290
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tag/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml424
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml366
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml241
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml184
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml204
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml202
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml304
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml21
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml303
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml378
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml164
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml12
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml221
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml175
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml156
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml205
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml192
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/aliases2
-rw-r--r--ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml170
325 files changed, 39095 insertions, 0 deletions
diff --git a/ansible_collections/cisco/aci/tests/integration/inventory.networking b/ansible_collections/cisco/aci/tests/integration/inventory.networking
new file mode 100644
index 000000000..16e3d1ee1
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/inventory.networking
@@ -0,0 +1,13 @@
+[aci]
+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
+
+[aci:vars]
+aci_username=ansible_github_ci
+aci_password="sJ94G92#8dq2hx*K4qh"
+ansible_connection=local
+ansible_python_interpreter=/usr/bin/python3.9
diff --git a/ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt b/ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt
new file mode 100644
index 000000000..7e23f90da
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt
@@ -0,0 +1,12 @@
+lxml
+cryptography
+pyOpenSSL
+netaddr
+ipaddress
+
+# requirement for aci_rest module
+xmljson
+lxml
+
+# requirement for aci_aaa_user module
+python-dateutil \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/target-prefixes.network b/ansible_collections/cisco/aci/tests/integration/target-prefixes.network
new file mode 100644
index 000000000..dc092c888
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/target-prefixes.network
@@ -0,0 +1 @@
+aci
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml
new file mode 100644
index 000000000..04b7070e2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_custom_privilege/tasks/main.yml
@@ -0,0 +1,237 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: Execute tasks only for ACI v5+
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure fabricPod custom privilege does not exists
+ cisco.aci.aci_aaa_custom_privilege: &fabric_pod_absent
+ <<: *aci_info
+ name: fabricPod
+ state: absent
+
+ - name: Add a custom privilege with check mode
+ cisco.aci.aci_aaa_custom_privilege: &cm_cp_present
+ <<: *fabric_pod_absent
+ description: My Custom Privilege
+ write_privilege: custom-privilege-1
+ read_privilege: custom-privilege-1
+ state: present
+ check_mode: true
+ register: cm_cp_present
+
+ - name: Assertions check for add a custom privilege with check mode
+ assert:
+ that:
+ - cm_cp_present is changed
+ - cm_cp_present.current | length == 0
+ - cm_cp_present.previous | length == 0
+ - cm_cp_present.sent.aaaRbacClassPriv.attributes.name == 'fabricPod'
+ - cm_cp_present.sent.aaaRbacClassPriv.attributes.descr == 'My Custom Privilege'
+ - cm_cp_present.sent.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-1'
+ - cm_cp_present.sent.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-1'
+
+ - name: Add a custom privilege with normal mode
+ cisco.aci.aci_aaa_custom_privilege: &nm_cp_present
+ <<: *cm_cp_present
+ register: nm_cp_present
+
+ - name: Assertions check for add a custom privilege with normal mode
+ assert:
+ that:
+ - nm_cp_present is changed
+ - nm_cp_present.current | length == 1
+ - nm_cp_present.previous | length == 0
+ - nm_cp_present.current.0.aaaRbacClassPriv.attributes.name == 'fabricPod'
+ - nm_cp_present.current.0.aaaRbacClassPriv.attributes.descr == 'My Custom Privilege'
+ - nm_cp_present.current.0.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-1'
+ - nm_cp_present.current.0.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-1'
+
+ - name: Add a custom privilege with normal mode - idempotency works
+ cisco.aci.aci_aaa_custom_privilege:
+ <<: *nm_cp_present
+ register: idempotency_cp_present
+
+ - name: Idempotency assertions check for add a custom privilege with normal mode
+ assert:
+ that:
+ - idempotency_cp_present is not changed
+ - idempotency_cp_present.current | length == 1
+ - idempotency_cp_present.previous | length == 1
+ - idempotency_cp_present.current.0.aaaRbacClassPriv.attributes.name == 'fabricPod'
+ - idempotency_cp_present.current.0.aaaRbacClassPriv.attributes.descr == 'My Custom Privilege'
+ - idempotency_cp_present.current.0.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-1'
+ - idempotency_cp_present.current.0.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-1'
+ - idempotency_cp_present.previous.0.aaaRbacClassPriv.attributes.name == 'fabricPod'
+ - idempotency_cp_present.previous.0.aaaRbacClassPriv.attributes.descr == 'My Custom Privilege'
+ - idempotency_cp_present.previous.0.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-1'
+ - idempotency_cp_present.previous.0.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-1'
+
+ - name: Ensure fvTenant custom privilege does not exists
+ cisco.aci.aci_aaa_custom_privilege: &fv_tenant_absent
+ <<: *aci_info
+ name: fvTenant
+ state: absent
+
+ - name: Add a custom privilege with none privileges
+ cisco.aci.aci_aaa_custom_privilege: &fv_tenant_present
+ <<: *fv_tenant_absent
+ state: present
+ register: cp_with_none_priv
+
+ - name: Assertions check for add a custom privilege with none privileges
+ assert:
+ that:
+ - cp_with_none_priv is changed
+ - cp_with_none_priv.current | length == 1
+ - cp_with_none_priv.previous | length == 0
+ - cp_with_none_priv.current.0.aaaRbacClassPriv.attributes.name == 'fvTenant'
+ - cp_with_none_priv.current.0.aaaRbacClassPriv.attributes.wPriv == ''
+ - cp_with_none_priv.current.0.aaaRbacClassPriv.attributes.rPriv == ''
+
+ - name: Update fv_tenant_present custom privilege with 'custom-privilege-2' privilege
+ cisco.aci.aci_aaa_custom_privilege:
+ <<: *fv_tenant_present
+ write_privilege: custom-privilege-2
+ read_privilege: custom-privilege-2
+ register: update_cp_with_priv
+
+ - name: Assertions check for update fv_tenant_present custom privilege with 'custom-privilege-2' privilege
+ assert:
+ that:
+ - update_cp_with_priv is changed
+ - update_cp_with_priv.current | length == 1
+ - update_cp_with_priv.previous | length == 1
+ - update_cp_with_priv.current.0.aaaRbacClassPriv.attributes.name == 'fvTenant'
+ - update_cp_with_priv.current.0.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-2'
+ - update_cp_with_priv.current.0.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-2'
+ - update_cp_with_priv.previous.0.aaaRbacClassPriv.attributes.wPriv == ''
+ - update_cp_with_priv.previous.0.aaaRbacClassPriv.attributes.rPriv == ''
+
+ - name: Update fv_tenant_present - write_privilege to 'custom-privilege-3' privilege
+ cisco.aci.aci_aaa_custom_privilege:
+ <<: *fv_tenant_present
+ write_privilege: custom-privilege-3
+ register: update_cp_w_priv_check
+
+ - name: Assertions check for update fv_tenant_present - write_privilege to 'custom-privilege-3' privilege
+ assert:
+ that:
+ - update_cp_w_priv_check is changed
+ - update_cp_w_priv_check.current | length == 1
+ - update_cp_w_priv_check.previous | length == 1
+ - update_cp_w_priv_check.current.0.aaaRbacClassPriv.attributes.name == 'fvTenant'
+ - update_cp_w_priv_check.current.0.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-3'
+ - update_cp_w_priv_check.current.0.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-2'
+ - update_cp_w_priv_check.previous.0.aaaRbacClassPriv.attributes.name == 'fvTenant'
+ - update_cp_w_priv_check.previous.0.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-2'
+ - update_cp_w_priv_check.previous.0.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-2'
+
+ - name: Query a custom privilege with name
+ cisco.aci.aci_aaa_custom_privilege:
+ <<: *aci_info
+ name: fabricPod
+ state: query
+ register: query_a_cp_with_name
+
+ - name: Assertions check for query a custom privilege with name
+ assert:
+ that:
+ - query_a_cp_with_name is not changed
+ - query_a_cp_with_name.current | length == 1
+ - query_a_cp_with_name.current.0.aaaRbacClassPriv.attributes.name == 'fabricPod'
+ - query_a_cp_with_name.current.0.aaaRbacClassPriv.attributes.wPriv == 'custom-privilege-1'
+ - query_a_cp_with_name.current.0.aaaRbacClassPriv.attributes.rPriv == 'custom-privilege-1'
+
+ - name: Query all custom privileges
+ cisco.aci.aci_aaa_custom_privilege:
+ <<: *aci_info
+ state: query
+ register: query_all_cp
+
+ - name: Assertions check for query all custom privileges
+ assert:
+ that:
+ - query_all_cp is not changed
+ - query_all_cp.current | length >= 2
+
+ - name: Remove a custom privilege with check mode
+ cisco.aci.aci_aaa_custom_privilege: &cm_cp_absent
+ <<: *aci_info
+ name: fabricPod
+ state: absent
+ check_mode: true
+ register: cm_cp_absent
+
+ - name: Assertions check for remove a custom privilege with check mode
+ assert:
+ that:
+ - cm_cp_absent is changed
+ - cm_cp_absent.current | length == 1
+ - cm_cp_absent.previous | length == 1
+ - cm_cp_absent.current.0.aaaRbacClassPriv.attributes.name == 'fabricPod'
+ - cm_cp_absent.previous.0.aaaRbacClassPriv.attributes.name == 'fabricPod'
+
+ - name: Remove a custom privilege with normal mode
+ cisco.aci.aci_aaa_custom_privilege: &nm_cp_absent
+ <<: *cm_cp_absent
+ register: nm_cp_absent
+
+ - name: Assertions check for remove a custom privilege with normal mode
+ assert:
+ that:
+ - nm_cp_absent is changed
+ - nm_cp_absent.current == []
+ - nm_cp_absent.previous | length == 1
+ - nm_cp_absent.previous.0.aaaRbacClassPriv.attributes.name == 'fabricPod'
+
+ - name: Remove a custom privilege with normal mode - idempotency works
+ cisco.aci.aci_aaa_custom_privilege:
+ <<: *nm_cp_absent
+ register: idempotency_cp_absent
+
+ - name: Idempotency assertions check for remove a custom privilege with normal mode
+ assert:
+ that:
+ - idempotency_cp_absent is not changed
+ - idempotency_cp_absent.current == []
+ - idempotency_cp_absent.previous == []
+
+ - name: Query a Removed custom privilege with name
+ cisco.aci.aci_aaa_custom_privilege:
+ <<: *aci_info
+ name: fabricPod
+ state: query
+ register: removed_cp_query_result
+
+ - name: Assertions check for Removed custom privilege with name
+ assert:
+ that:
+ - removed_cp_query_result is not changed
+ - removed_cp_query_result.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml
new file mode 100644
index 000000000..55eaaff79
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_domain/tasks/main.yml
@@ -0,0 +1,227 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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 anstest_sec_domain does not exists
+ cisco.aci.aci_aaa_domain: &sec_domain_absent
+ <<: *aci_info
+ name: anstest_sec_domain
+ description: "Anstest Sec Domain Descr"
+ state: absent
+
+- name: Add anstest_sec_domain security domain with check mode
+ cisco.aci.aci_aaa_domain: &cm_sec_domain_present
+ <<: *sec_domain_absent
+ state: present
+ check_mode: true
+ register: cm_sec_domain_present
+
+- name: Assertions check for add anstest_sec_domain security domain with check mode
+ assert:
+ that:
+ - cm_sec_domain_present is changed
+ - cm_sec_domain_present.current | length == 0
+ - cm_sec_domain_present.previous | length == 0
+ - cm_sec_domain_present.sent.aaaDomain.attributes.name == 'anstest_sec_domain'
+
+- name: Add anstest_sec_domain security domain with normal mode
+ cisco.aci.aci_aaa_domain: &nm_sec_domain_present
+ <<: *cm_sec_domain_present
+ register: nm_sec_domain_present
+
+- name: Assertions check for add anstest_sec_domain security domain with normal mode
+ assert:
+ that:
+ - nm_sec_domain_present is changed
+ - nm_sec_domain_present.current | length == 1
+ - nm_sec_domain_present.previous | length == 0
+ - nm_sec_domain_present.current.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+
+- name: Assertions check for nm_sec_domain_present in v5.0+
+ assert:
+ that:
+ - nm_sec_domain_present.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+- name: Add anstest_sec_domain security domain with normal mode - idempotency works
+ cisco.aci.aci_aaa_domain:
+ <<: *nm_sec_domain_present
+ register: idempotency_sec_domain_present
+
+- name: Idempotency assertions check for add anstest_sec_domain security domain with normal mode
+ assert:
+ that:
+ - idempotency_sec_domain_present is not changed
+ - idempotency_sec_domain_present.current | length == 1
+ - idempotency_sec_domain_present.previous | length == 1
+ - idempotency_sec_domain_present.current.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+ - idempotency_sec_domain_present.previous.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+
+- name: Assertions check for idempotency_sec_domain_present in v5.0+
+ assert:
+ that:
+ - idempotency_sec_domain_present.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ - idempotency_sec_domain_present.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+- name: Execute tasks only for ACI v5+
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Update anstest_sec_domain security domain restricted_rbac_domain state to true
+ cisco.aci.aci_aaa_domain:
+ <<: *nm_sec_domain_present
+ restricted_rbac_domain: true
+ register: update_sec_domain_present_true
+
+ - name: Assertions check for update anstest_sec_domain security domain restricted_rbac_domain state to true
+ assert:
+ that:
+ - update_sec_domain_present_true is changed
+ - update_sec_domain_present_true.current | length == 1
+ - update_sec_domain_present_true.previous | length == 1
+ - update_sec_domain_present_true.current.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+ - update_sec_domain_present_true.current.0.aaaDomain.attributes.restrictedRbacDomain == 'yes'
+ - update_sec_domain_present_true.sent.aaaDomain.attributes.restrictedRbacDomain == 'yes'
+ - update_sec_domain_present_true.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+
+ - name: Update anstest_sec_domain security domain restricted_rbac_domain state to false
+ cisco.aci.aci_aaa_domain:
+ <<: *nm_sec_domain_present
+ restricted_rbac_domain: false
+ register: update_sec_domain_present_false
+
+ - name: Assertions check for update anstest_sec_domain security domain restricted_rbac_domain state to false
+ assert:
+ that:
+ - update_sec_domain_present_false is changed
+ - update_sec_domain_present_false.current | length == 1
+ - update_sec_domain_present_false.previous | length == 1
+ - update_sec_domain_present_false.current.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+ - update_sec_domain_present_false.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ - update_sec_domain_present_false.sent.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ - update_sec_domain_present_false.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'yes'
+
+- name: Query a security domain with name
+ cisco.aci.aci_aaa_domain:
+ <<: *aci_info
+ name: anstest_sec_domain
+ state: query
+ register: query_sec_domain_with_name
+
+- name: Assertions check for query a security domain with name
+ assert:
+ that:
+ - query_sec_domain_with_name is not changed
+ - query_sec_domain_with_name.current | length == 1
+ - query_sec_domain_with_name.current.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+ - query_sec_domain_with_name.current.0.aaaDomain.attributes.descr == 'Anstest Sec Domain Descr'
+
+- name: Assertions check for query_sec_domain_with_name in v5.0+
+ assert:
+ that:
+ - query_sec_domain_with_name.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+- name: Query all security domains
+ cisco.aci.aci_aaa_domain:
+ <<: *aci_info
+ state: query
+ register: query_all_sec_domains
+
+- name: Assertions check for query all security domains
+ assert:
+ that:
+ - query_all_sec_domains is not changed
+ - query_all_sec_domains.current | length >= 1
+
+- name: Remove anstest_sec_domain security domain with check mode
+ cisco.aci.aci_aaa_domain: &cm_sec_domain_absent
+ <<: *nm_sec_domain_present
+ state: absent
+ check_mode: true
+ register: cm_sec_domain_absent
+
+- name: Assertions check for remove anstest_sec_domain security domain with check mode
+ assert:
+ that:
+ - cm_sec_domain_absent is changed
+ - cm_sec_domain_absent.current | length == 1
+ - cm_sec_domain_absent.previous | length == 1
+ - cm_sec_domain_absent.current.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+ - cm_sec_domain_absent.previous.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+
+- name: Assertions check for cm_sec_domain_absent in v5.0+
+ assert:
+ that:
+ - cm_sec_domain_absent.current.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ - cm_sec_domain_absent.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+- name: Remove anstest_sec_domain security domain with normal mode
+ cisco.aci.aci_aaa_domain: &nm_sec_domain_absent
+ <<: *cm_sec_domain_absent
+ register: nm_sec_domain_absent
+
+- name: Assertions check for remove anstest_sec_domain security domain with normal mode
+ assert:
+ that:
+ - nm_sec_domain_absent is changed
+ - nm_sec_domain_absent.current | length == 0
+ - nm_sec_domain_absent.previous | length == 1
+ - nm_sec_domain_absent.previous.0.aaaDomain.attributes.name == 'anstest_sec_domain'
+
+- name: Assertions check for nm_sec_domain_absent in v5.0+
+ assert:
+ that:
+ - nm_sec_domain_absent.previous.0.aaaDomain.attributes.restrictedRbacDomain == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+- name: Remove anstest_sec_domain security domain with normal mode - idempotency works
+ cisco.aci.aci_aaa_domain:
+ <<: *nm_sec_domain_absent
+ register: idempotency_sec_domain_absent
+
+- name: Idempotency assertions check for remove anstest_sec_domain security domain with normal mode
+ assert:
+ that:
+ - idempotency_sec_domain_absent is not changed
+ - idempotency_sec_domain_absent.current | length == 0
+ - idempotency_sec_domain_absent.previous | length == 0
+
+- name: Query a removed security domain with name
+ cisco.aci.aci_aaa_domain:
+ <<: *aci_info
+ name: anstest_sec_domain
+ state: query
+ register: removed_sec_domain_with_name
+
+- name: Assertions check for query a removed security domain with name
+ assert:
+ that:
+ - removed_sec_domain_with_name is not changed
+ - removed_sec_domain_with_name.current | length == 0
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml
new file mode 100644
index 000000000..dce0fd4c6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_role/tasks/main.yml
@@ -0,0 +1,229 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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 an anstest_role aaa role does not exists
+ cisco.aci.aci_aaa_role: &anstest_role_absent
+ <<: *aci_info
+ name: anstest_role
+ state: absent
+
+- name: Add an anstest_role aaa role with check mode
+ cisco.aci.aci_aaa_role: &cm_anstest_role_present
+ <<: *anstest_role_absent
+ priv: aaa
+ state: present
+ check_mode: true
+ register: cm_anstest_role_present
+
+- name: Assertions check for add an anstest_role aaa role with check mode
+ assert:
+ that:
+ - cm_anstest_role_present is changed
+ - cm_anstest_role_present.current | length == 0
+ - cm_anstest_role_present.previous | length == 0
+ - cm_anstest_role_present.sent.aaaRole.attributes.name == 'anstest_role'
+ - cm_anstest_role_present.sent.aaaRole.attributes.priv == 'aaa'
+
+- name: Add an anstest_role aaa role with normal mode
+ cisco.aci.aci_aaa_role: &nm_anstest_role_present
+ <<: *cm_anstest_role_present
+ register: nm_anstest_role_present
+
+- name: Assertions check for add an anstest_role aaa role with normal mode
+ assert:
+ that:
+ - nm_anstest_role_present is changed
+ - nm_anstest_role_present.current | length == 1
+ - nm_anstest_role_present.previous | length == 0
+ - nm_anstest_role_present.current.0.aaaRole.attributes.name == 'anstest_role'
+ - nm_anstest_role_present.current.0.aaaRole.attributes.priv == 'aaa'
+
+- name: Add an anstest_role aaa role with normal mode - idempotency works
+ cisco.aci.aci_aaa_role:
+ <<: *nm_anstest_role_present
+ register: idempotency_anstest_role_present
+
+- name: Idempotency assertions check for add an anstest_role aaa role with normal mode
+ assert:
+ that:
+ - idempotency_anstest_role_present is not changed
+ - idempotency_anstest_role_present.current | length == 1
+ - idempotency_anstest_role_present.previous | length == 1
+ - idempotency_anstest_role_present.current.0.aaaRole.attributes.name == 'anstest_role'
+ - idempotency_anstest_role_present.previous.0.aaaRole.attributes.name == 'anstest_role'
+ - idempotency_anstest_role_present.current.0.aaaRole.attributes.priv == 'aaa'
+ - idempotency_anstest_role_present.previous.0.aaaRole.attributes.priv == 'aaa'
+
+- name: Update an anstest_role with list of privileges
+ cisco.aci.aci_aaa_role:
+ <<: *nm_anstest_role_present
+ priv: [ "admin", "aaa", "tenant-connectivity"]
+ register: anstest_role_with_list_priv
+
+- name: Assertions check for update an anstest_role with list of privileges
+ assert:
+ that:
+ - anstest_role_with_list_priv is changed
+ - anstest_role_with_list_priv.current | length == 1
+ - anstest_role_with_list_priv.previous | length == 1
+ - anstest_role_with_list_priv.current.0.aaaRole.attributes.name == 'anstest_role'
+ - anstest_role_with_list_priv.previous.0.aaaRole.attributes.name == 'anstest_role'
+ - anstest_role_with_list_priv.previous.0.aaaRole.attributes.priv == 'aaa'
+
+- name: Assertions check for anstest_role_with_list_priv on v4.2 or earlier
+ assert:
+ that:
+ - anstest_role_with_list_priv.current.0.aaaRole.attributes.priv == 'aaa,admin'
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+- name: Assertions check for anstest_role_with_list_priv on v5+
+ assert:
+ that:
+ - anstest_role_with_list_priv.current.0.aaaRole.attributes.priv == 'aaa,admin,tenant-connectivity'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+
+- name: Update an anstest_role with admin privilege
+ cisco.aci.aci_aaa_role:
+ <<: *nm_anstest_role_present
+ priv: "admin"
+ register: anstest_role_with_valid_priv
+
+- name: Assertions check for update an anstest_role with admin privilege
+ assert:
+ that:
+ - anstest_role_with_valid_priv is changed
+ - anstest_role_with_valid_priv.current | length == 1
+ - anstest_role_with_valid_priv.previous | length == 1
+ - anstest_role_with_valid_priv.current.0.aaaRole.attributes.name == 'anstest_role'
+ - anstest_role_with_valid_priv.previous.0.aaaRole.attributes.name == 'anstest_role'
+ - anstest_role_with_valid_priv.current.0.aaaRole.attributes.priv == 'admin'
+
+- name: Assertions check for anstest_role_with_valid_priv on v4.2 or earlier
+ assert:
+ that:
+ - anstest_role_with_valid_priv.previous.0.aaaRole.attributes.priv == 'aaa,admin'
+ when: version.current.0.topSystem.attributes.version is version('5', '<')
+
+- name: Assertions check for anstest_role_with_valid_priv on v5+
+ assert:
+ that:
+ - anstest_role_with_valid_priv.previous.0.aaaRole.attributes.priv == 'aaa,admin,tenant-connectivity'
+ when: version.current.0.topSystem.attributes.version is version('5', '>=')
+
+- name: Update an anstest_role with invalid list of privileges
+ cisco.aci.aci_aaa_role:
+ <<: *nm_anstest_role_present
+ priv: [ "admin", "aaa", "tenant-connectivity123"]
+ register: anstest_role_with_invalid_list_priv
+ ignore_errors: true
+
+- name: Update an anstest_role with invalid privilege
+ cisco.aci.aci_aaa_role:
+ <<: *nm_anstest_role_present
+ priv: "admin123"
+ register: anstest_role_with_invalid_priv
+ ignore_errors: true
+
+- name: Assertions check for query a aaa role with name
+ assert:
+ that:
+ - anstest_role_with_invalid_list_priv.msg.startswith("value of privileges must be one or more of")
+ - anstest_role_with_invalid_priv.msg.startswith("value of privileges must be one or more of")
+
+- name: Query an aaa role with name
+ cisco.aci.aci_aaa_role:
+ <<: *aci_info
+ name: anstest_role
+ state: query
+ register: anstest_role_query_result
+
+- name: Assertions check for query a aaa role with name
+ assert:
+ that:
+ - anstest_role_query_result is not changed
+ - anstest_role_query_result.current | length == 1
+ - anstest_role_query_result.current.0.aaaRole.attributes.name == 'anstest_role'
+ - anstest_role_query_result.current.0.aaaRole.attributes.priv == 'admin'
+
+- name: Query all aaa roles
+ cisco.aci.aci_aaa_role:
+ <<: *aci_info
+ state: query
+ register: query_all_roles
+
+- name: Assertions check for query all aaa roles
+ assert:
+ that:
+ - query_all_roles is not changed
+ - query_all_roles.current | length >= 1
+
+- name: Remove an anstest_role aaa role with check mode
+ cisco.aci.aci_aaa_role: &cm_anstest_role_absent
+ <<: *nm_anstest_role_present
+ state: absent
+ check_mode: true
+ register: cm_anstest_role_absent
+
+- name: Assertions check for remove an anstest_role aaa role with check mode
+ assert:
+ that:
+ - cm_anstest_role_absent is changed
+ - cm_anstest_role_absent.current | length == 1
+ - cm_anstest_role_absent.previous | length == 1
+ - cm_anstest_role_absent.current.0.aaaRole.attributes.name == 'anstest_role'
+ - cm_anstest_role_absent.previous.0.aaaRole.attributes.name == 'anstest_role'
+ - cm_anstest_role_absent.current.0.aaaRole.attributes.priv == 'admin'
+ - cm_anstest_role_absent.previous.0.aaaRole.attributes.priv == 'admin'
+
+- name: Remove an anstest_role aaa role with normal mode
+ cisco.aci.aci_aaa_role: &nm_anstest_role_absent
+ <<: *cm_anstest_role_absent
+ register: nm_anstest_role_absent
+
+- name: Assertions check for remove an anstest_role aaa role with normal mode
+ assert:
+ that:
+ - nm_anstest_role_absent is changed
+ - nm_anstest_role_absent.current | length == 0
+ - nm_anstest_role_absent.previous | length == 1
+ - nm_anstest_role_absent.previous.0.aaaRole.attributes.name == 'anstest_role'
+ - nm_anstest_role_absent.previous.0.aaaRole.attributes.priv == 'admin'
+
+- name: Remove an anstest_role aaa role with normal mode - idempotency works
+ cisco.aci.aci_aaa_role:
+ <<: *nm_anstest_role_absent
+ register: idempotency_anstest_role_absent
+
+- name: Idempotency assertions check for remove an anstest_role aaa role with normal mode
+ assert:
+ that:
+ - idempotency_anstest_role_absent is not changed
+ - idempotency_anstest_role_absent.current | length == 0
+ - idempotency_anstest_role_absent.previous | length == 0
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/pki/sshkey.pub b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/pki/sshkey.pub
new file mode 100644
index 000000000..3602ccd7e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/pki/sshkey.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHL9VwXtwdyTC8lC0FAT4Ss8g0TnYJQf+zJiFlzUBiioqyblvr3w6xwgm5B5oghWag/IwK8c43rxvrW9Yn45xhU= ansible@example \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml
new file mode 100644
index 000000000..46113c0f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_ssh_auth/tasks/main.yml
@@ -0,0 +1,164 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, Tim Cragg (timcragg) <tcragg@cisco.com>
+# Copyright: (c) 2017, Dag Wieers (dagwieers) <dag@wieers.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: '{{ aci_output_level | default("info") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove any pre-existing user
+ cisco.aci.aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible
+ state: absent
+
+# ADD USER
+- name: Create AAA user
+ cisco.aci.aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible
+ aaa_password: 12!Ab:cD!34
+ state: present
+
+
+# ADD SSH AUTH
+- name: Add a new SSH Key (Check Mode)
+ cisco.aci.aci_aaa_ssh_auth: &ssh_key_present
+ <<: *aci_info
+ aaa_user: ansible
+ auth_name: ansible_key
+ data: "{{ lookup('file', 'pki/sshkey.pub') }}"
+ state: present
+ check_mode: true
+ register: cm_add_ssh_key
+
+- name: Add a new SSH Key (Normal Mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_present
+ register: nm_add_ssh_key
+
+- name: Add SSH key again (Check Mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_present
+ check_mode: true
+ register: cm_add_ssh_key_again
+
+- name: Add SSH key again (Normal Mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_present
+ register: nm_add_ssh_key_again
+
+- name: Verify add SSH key
+ assert:
+ that:
+ - cm_add_ssh_key is changed
+ - nm_add_ssh_key is changed
+ - nm_add_ssh_key.current.0.aaaSshAuth.attributes.dn == 'uni/userext/user-ansible/sshauth-ansible_key'
+ - nm_add_ssh_key.current.0.aaaSshAuth.attributes.name == 'ansible_key'
+ - nm_add_ssh_key.current.0.aaaSshAuth.attributes.data == lookup('file', 'pki/sshkey.pub')
+ - cm_add_ssh_key_again is not changed
+ - nm_add_ssh_key_again is not changed
+ - nm_add_ssh_key_again.current.0.aaaSshAuth.attributes.dn == 'uni/userext/user-ansible/sshauth-ansible_key'
+ - nm_add_ssh_key_again.current.0.aaaSshAuth.attributes.name == 'ansible_key'
+ - nm_add_ssh_key_again.current.0.aaaSshAuth.attributes.data == lookup('file', 'pki/sshkey.pub')
+
+# QUERY ALL SSH KEYS
+- name: Query all SSH keys (check mode)
+ cisco.aci.aci_aaa_ssh_auth: &ssh_key_query_all
+ <<: *aci_info
+ aaa_user: ansible
+ state: query
+ check_mode: true
+ register: cm_query_all_ssh_keys
+
+- name: Query all SSH keys (normal mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_query_all
+ register: nm_query_all_ssh_keys
+
+- name: Verify query_all_ssh_keys
+ assert:
+ that:
+ - cm_query_all_ssh_keys is not changed
+ - nm_query_all_ssh_keys is not changed
+
+# QUERY OUR SSH KEY
+- name: Query our SSH key (check mode)
+ cisco.aci.aci_aaa_ssh_auth: &ssh_key_query
+ <<: *ssh_key_query_all
+ auth_name: ansible_key
+ check_mode: true
+ register: cm_query_ssh_key
+
+- name: Query our SSH key (normal mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_query
+ register: nm_query_ssh_key
+
+- name: Verify query_ssh_key
+ assert:
+ that:
+ - cm_query_ssh_key is not changed
+ - nm_query_ssh_key is not changed
+ - nm_query_ssh_key.current.0.aaaSshAuth.attributes.dn == 'uni/userext/user-ansible/sshauth-ansible_key'
+ - nm_query_ssh_key.current.0.aaaSshAuth.attributes.name == 'ansible_key'
+ - nm_query_ssh_key.current.0.aaaSshAuth.attributes.data == lookup('file', 'pki/sshkey.pub')
+ - cm_query_ssh_key == nm_query_ssh_key
+
+# REMOVE SSH KEY
+- name: Remove SSH key (check mode)
+ cisco.aci.aci_aaa_ssh_auth: &ssh_key_absent
+ <<: *aci_info
+ aaa_user: ansible
+ auth_name: ansible_key
+ data: "{{ lookup('file', 'pki/sshkey.pub') }}"
+ state: absent
+ check_mode: true
+ register: cm_remove_ssh_key
+
+- name: Remove SSH key (normal mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_absent
+ register: nm_remove_ssh_key
+
+- name: Remove SSH key again (check mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_absent
+ check_mode: true
+ register: cm_remove_ssh_key_again
+
+- name: Remove SSH key again (normal mode)
+ cisco.aci.aci_aaa_ssh_auth:
+ <<: *ssh_key_absent
+ register: nm_remove_ssh_key_again
+
+- name: Verify remove_user
+ assert:
+ that:
+ - cm_remove_ssh_key is changed
+ - nm_remove_ssh_key is changed
+ - nm_remove_ssh_key.current == []
+ - cm_remove_ssh_key_again is not changed
+ - nm_remove_ssh_key_again is not changed
+
+# CLEAN UP
+- name: Remove user
+ cisco.aci.aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..56de63830
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml
@@ -0,0 +1,236 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (dagwieers) <dag@wieers.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
+
+
+# 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
+ 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
+ description: Ansible test user
+ email: ansible@ansible.lan
+ enabled: true
+ expiration: never
+ expires: false
+ first_name: Test
+ last_name: User
+ phone: 1-234-555-678
+ check_mode: true
+ register: cm_add_user
+
+# NOTE: Setting password is not idempotent, see #35544
+- name: Add user (normal mode)
+ cisco.aci.aci_aaa_user:
+ <<: *user_present
+ aaa_password: 12!Ab:cD!34
+ register: nm_add_user
+
+- name: Add user again (check mode)
+ cisco.aci.aci_aaa_user: *user_present
+ check_mode: true
+ register: cm_add_user_again
+
+- name: Add user again (normal mode)
+ cisco.aci.aci_aaa_user: *user_present
+ register: nm_add_user_again
+
+- name: Verify add user
+ assert:
+ that:
+ - cm_add_user is changed
+ - nm_add_user is changed
+ - nm_add_user.current.0.aaaUser.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_user.current.0.aaaUser.attributes.descr == 'Ansible test user'
+ - cm_add_user_again is not changed
+ - 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
+ 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
+ description: Ansible test user for integration tests
+ email: aci-ansible@ansible.lan
+ expiration: '2123-12-12'
+ expires: true
+ phone: 2-345-555-678
+ check_mode: true
+ register: cm_modify_user
+
+- name: Modify user (normal mode)
+ cisco.aci.aci_aaa_user: *user_changed
+ register: nm_modify_user
+
+- name: Modify user again (check mode)
+ cisco.aci.aci_aaa_user: *user_changed
+ check_mode: true
+ register: cm_modify_user_again
+
+- name: Modify user again (normal mode)
+ cisco.aci.aci_aaa_user: *user_changed
+ register: nm_modify_user_again
+
+- name: Verify modify user
+ assert:
+ that:
+ - cm_modify_user is changed
+ - 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
+ - nm_modify_user_again is not changed
+ - nm_modify_user_again.current.0.aaaUser.attributes.descr == 'Ansible test user for integration tests'
+
+
+# CLEAR PASSWORD HISTORY
+- name: Clear password history (check_mode)
+ cisco.aci.aci_aaa_user: &clear_password_history
+ 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
+ clear_password_history: true
+ check_mode: true
+ register: cm_clear_password_history
+
+- name: Clear password history (normal mode)
+ cisco.aci.aci_aaa_user: *clear_password_history
+ register: nm_clear_password_history
+
+- name: Clear password history (check mode)
+ cisco.aci.aci_aaa_user: *clear_password_history
+ check_mode: true
+ register: cm_clear_password_history_again
+
+- name: Clear password history (normal mode)
+ cisco.aci.aci_aaa_user: *clear_password_history
+ register: nm_clear_password_history_again
+
+- name: Verify clear password history
+ assert:
+ that:
+ # NOTE: Clearing password history is a changing action, everytime
+ - cm_clear_password_history is changed
+ - nm_clear_password_history is changed
+ - cm_clear_password_history_again is changed
+ - nm_clear_password_history_again is changed
+
+
+# QUERY ALL USERS
+- name: Query all users (check_mode)
+ cisco.aci.aci_aaa_user: &user_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") }}'
+ aaa_user: ansible
+ state: query
+ check_mode: true
+ register: cm_query_all_users
+
+- name: Query all users (normal mode)
+ cisco.aci.aci_aaa_user: *user_query
+ register: nm_query_all_users
+
+- name: Verify query_all_users
+ assert:
+ that:
+ - cm_query_all_users is not changed
+ - nm_query_all_users is not changed
+ # NOTE: Order of users is not stable between calls
+ #- cm_query_all_users == nm_query_all_users
+
+
+# QUERY OUR USER
+- name: Query our user (check_mode)
+ cisco.aci.aci_aaa_user:
+ <<: *user_query
+ check_mode: true
+ register: cm_query_user
+
+- name: Query our user (normal mode)
+ cisco.aci.aci_aaa_user:
+ <<: *user_query
+ register: nm_query_user
+
+- name: Verify query_user
+ assert:
+ that:
+ - cm_query_user is not changed
+ - nm_query_user is not changed
+ - cm_query_user == nm_query_user
+ - nm_query_user.current.0.aaaUser.attributes.accountStatus == 'active'
+ - nm_query_user.current.0.aaaUser.attributes.descr == 'Ansible test user for integration tests'
+ - nm_query_user.current.0.aaaUser.attributes.email == 'aci-ansible@ansible.lan'
+ - nm_query_user.current.0.aaaUser.attributes.expiration == '2123-12-12T00:00:00.000+00:00'
+ - nm_query_user.current.0.aaaUser.attributes.expires == 'yes'
+ - nm_query_user.current.0.aaaUser.attributes.phone == '2-345-555-678'
+
+
+# REMOVE USER
+- name: Remove user (check_mode)
+ cisco.aci.aci_aaa_user: *user_absent
+ check_mode: true
+ register: cm_remove_user
+
+- name: Remove user (normal mode)
+ cisco.aci.aci_aaa_user: *user_absent
+ register: nm_remove_user
+
+- name: Remove user again (check_mode)
+ cisco.aci.aci_aaa_user: *user_absent
+ check_mode: true
+ register: cm_remove_user_again
+
+- name: Remove user again (normal mode)
+ cisco.aci.aci_aaa_user: *user_absent
+ register: nm_remove_user_again
+
+- name: Verify remove_user
+ assert:
+ that:
+ - cm_remove_user is changed
+ - nm_remove_user is changed
+ - cm_remove_user_again is not changed
+ - nm_remove_user_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt
new file mode 100644
index 000000000..cfac5531e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/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_aaa_user_certificate/pki/admin.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.key
new file mode 100644
index 000000000..63bb00cc0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/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_aaa_user_certificate/pki/admin_invalid.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin_invalid.key
new file mode 100644
index 000000000..22f5fae45
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/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_aaa_user_certificate/pki/openssh_rsa.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/openssh_rsa.key
new file mode 100644
index 000000000..0c18da5c5
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/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_aaa_user_certificate/pki/rsa_ansible.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key
new file mode 100644
index 000000000..ac63a0055
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/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_aaa_user_certificate/pki/rsa_user.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt
new file mode 100644
index 000000000..de2223500
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/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_aaa_user_certificate/pki/rsa_user.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key
new file mode 100644
index 000000000..354dbbdbb
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/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_aaa_user_certificate/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml
new file mode 100644
index 000000000..9d300e4d7
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml
@@ -0,0 +1,346 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (dagwieers) <dag@wieers.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: Making sure current user has correct cert
+ cisco.aci.aci_aaa_user_certificate:
+ 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: '{{ aci_username }}'
+ name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+
+- name: Remove any pre-existing certificate
+ cisco.aci.aci_aaa_user_certificate: &cert_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: '{{ aci_username }}'
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - admin
+ - user
+ - rsa_user
+
+# ADD USER CERTIFICATE
+- name: Add user certificate (check_mode)
+ cisco.aci.aci_aaa_user_certificate: &cert_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") }}'
+ aaa_user: '{{ aci_username }}'
+ name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+ check_mode: true
+ register: cm_add_cert
+
+- name: Add user certificate (normal mode)
+ cisco.aci.aci_aaa_user_certificate: *cert_present
+ register: nm_add_cert
+
+- name: Add user certificate again (check mode)
+ cisco.aci.aci_aaa_user_certificate: *cert_present
+ check_mode: true
+ register: cm_add_cert_again
+
+- name: Add user certificate again (normal mode)
+ cisco.aci.aci_aaa_user_certificate: *cert_present
+ register: nm_add_cert_again
+
+- name: Verify add_cert
+ assert:
+ that:
+ - cm_add_cert is changed
+ - nm_add_cert is change
+ - nm_add_cert.current.0.aaaUserCert.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_cert_again is not changed
+ - nm_add_cert_again is not changed
+
+- name: Add rsa_user certificates
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_present
+ name: "{{ item }}"
+ certificate: "{{ lookup('file', 'pki/rsa_user.crt') }}"
+ state: present
+ loop:
+ - user
+ - rsa_user
+
+- name: Add admin certificate with user name
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_present
+ name: '{{ aci_username }}'
+ state: present
+
+# QUERY ALL USER CERTIFICATES
+- name: Query all user certificates using signature-based authentication (check_mode)
+ cisco.aci.aci_aaa_user_certificate: &cert_query
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ certificate_name: admin
+ private_key: '{{ role_path }}/pki/admin.key'
+ 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: '{{ aci_username }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_certs
+
+- name: Query all user certificates using signature-based authentication (normal mode)
+ cisco.aci.aci_aaa_user_certificate: *cert_query
+ register: nm_query_all_certs
+
+- name: Verify query_all_certs
+ assert:
+ that:
+ - cm_query_all_certs is not changed
+ - nm_query_all_certs is not changed
+ # NOTE: Order of certs is not stable between calls
+ #- cm_query_all_certs == nm_query_all_certs
+
+- name: Query all user certificates using signature-based authentication (valid rsa private key)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ private_key: '{{ role_path }}/pki/rsa_user.key'
+ certificate_name: rsa_user
+ register: nm_query_all_rsa
+
+- name: Verify nm_query_all_rsa
+ assert:
+ that:
+ - nm_query_all_rsa is not changed
+ - nm_query_all_rsa.current.0.aaaUser.children | length >= 4
+
+- name: Query all certificates using signature-based authentication (private key content for admin certificate)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ 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-----
+ register: nm_query_all_key_content
+
+# QUERY OUR USER CERTIFICATE
+- name: Query our certificate using signature-based authentication (check_mode)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ name: admin
+ check_mode: true
+ register: cm_query_cert
+
+- name: Query our certificate using signature-based authentication (normal mode)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ name: admin
+ register: nm_query_cert
+
+- name: Verify query_cert
+ assert:
+ that:
+ - cm_query_cert is not changed
+ - nm_query_cert is not changed
+ - cm_query_cert == nm_query_cert
+
+- name: Query our certificate using signature-based authentication (invalid private key file)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ private_key: '{{ role_path }}/pki/admin_invalid.key'
+ name: admin
+ register: query_cert_invalid_key
+ ignore_errors: true
+
+- name: Query our certificate using signature-based authentication (certificate file)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ private_key: '{{ role_path }}/pki/admin.crt'
+ name: admin
+ register: query_cert_valid_key
+ ignore_errors: true
+
+- name: Query our certificate using signature-based authentication (ansible rsa private key file)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ private_key: '{{ role_path }}/pki/rsa_ansible.key'
+ certificate_name: rsa_user
+ name: rsa_user
+ register: query_cert_openssh_rsa_key
+ ignore_errors: true
+
+- name: Query our certificate using signature-based authentication (valid rsa private key file)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ private_key: '{{ role_path }}/pki/rsa_user.key'
+ certificate_name: rsa_user
+ name: "{{ item }}"
+ register: query_cert_ansible_rsa_key
+ loop:
+ - "rsa_user"
+ - "user"
+
+- name: Query our certificate using signature-based authentication (private key content for rsa_user certificate)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ private_key: |
+ -----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-----
+ certificate_name: rsa_user
+ name: "{{ item }}"
+ register: query_cert_key_content
+ loop:
+ - "rsa_user"
+ - "user"
+
+# REMOVE CERTIFICATE
+- name: Remove certificate (check_mode)
+ cisco.aci.aci_aaa_user_certificate: &cert_delete
+ 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: '{{ aci_username }}'
+ name: admin
+ state: absent
+ check_mode: true
+ register: cm_remove_cert
+
+- name: Remove certificate (normal mode)
+ cisco.aci.aci_aaa_user_certificate: *cert_delete
+ register: nm_remove_cert
+
+- name: Remove certificate again (check_mode)
+ cisco.aci.aci_aaa_user_certificate: *cert_delete
+ check_mode: true
+ register: cm_remove_cert_again
+
+- name: Remove certificate again (normal mode)
+ cisco.aci.aci_aaa_user_certificate: *cert_delete
+ register: nm_remove_cert_again
+
+- name: Verify remove_cert
+ assert:
+ that:
+ - cm_remove_cert is changed
+ - nm_remove_cert is changed
+ - cm_remove_cert_again is not changed
+ - nm_remove_cert_again is not changed
+
+# Checking if changing certification_name to name throws an error. (#82)
+- name: Making sure current user has correct cert
+ aci_aaa_user_certificate:
+ <<: *aci_info
+ aaa_user: '{{ aci_username }}'
+ name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+
+- name: Remove user ansible_test
+ aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible_test
+ state: absent
+
+- name: Add user ansible_test
+ aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible_test
+ aaa_password: ansible_5351
+ expiration: never
+ expires: false
+ state: present
+
+- name: Add user certificate
+ aci_aaa_user_certificate:
+ <<: *aci_info
+ aaa_user: ansible_test
+ name: test
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+
+- name: Query test certificate
+ aci_aaa_user_certificate:
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ certificate_name: admin
+ private_key: '{{ role_path }}/pki/admin.key'
+ aaa_user: ansible_test
+ name: test
+ state: query
+ register: query_test
+
+- name: Verify query_test
+ assert:
+ that:
+ - query_test is not changed
+
+- name: Remove user to clean environment for next test on ci
+ aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible_test
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml
new file mode 100644
index 000000000..ac0d1d0f2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_domain/tasks/main.yml
@@ -0,0 +1,224 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, Tim Cragg (timcragg) <tcragg@cisco.com>
+# Copyright: (c) 2022, Sabari Jaganathan (@sajagana)
+# Copyright: (c) 2017, Dag Wieers (dagwieers) <dag@wieers.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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove user domain from a aaa_user
+ cisco.aci.aci_aaa_user_domain:
+ <<: *aci_info
+ name: anstest-security-domain
+ aaa_user: ansible
+ state: absent
+
+- name: Remove user domain from a aaa_user
+ cisco.aci.aci_aaa_user_domain:
+ <<: *aci_info
+ name: anstest-security-domain-1
+ aaa_user: ansible
+ state: absent
+
+- name: Remove any pre-existing user
+ cisco.aci.aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible
+ state: absent
+
+# ADD USER
+- name: Add a aaa_user
+ cisco.aci.aci_aaa_user: &user_present
+ <<: *aci_info
+ aaa_user: ansible
+ aaa_password: 12!Ab:cD!34
+ description: Ansible test user
+ email: ansible@ansible.lan
+ enabled: true
+ expiration: never
+ expires: false
+ first_name: Ansible
+ last_name: User
+ phone: 1-234-555-678
+ register: add_user
+
+# ADD AAA USER DOMAIN
+- name: Add user domain to aaa_user with check mode
+ cisco.aci.aci_aaa_user_domain: &cm_sec_domain_present
+ <<: *aci_info
+ name: anstest-security-domain
+ aaa_user: ansible
+ state: present
+ check_mode: true
+ register: cm_sec_domain_present
+
+- name: Assertions check for add user domain to aaa_user with check mode
+ assert:
+ that:
+ - cm_sec_domain_present is changed
+ - cm_sec_domain_present.current | length == 0
+ - cm_sec_domain_present.previous | length == 0
+ - cm_sec_domain_present.sent.aaaUserDomain.attributes.name == 'anstest-security-domain'
+
+- name: Add user domain to aaa_user with normal mode
+ cisco.aci.aci_aaa_user_domain: &nm_sec_domain_present
+ <<: *cm_sec_domain_present
+ register: nm_sec_domain_present
+
+- name: Assertions check for add user domain to aaa_user with normal mode
+ assert:
+ that:
+ - nm_sec_domain_present is changed
+ - nm_sec_domain_present.current | length == 1
+ - nm_sec_domain_present.previous | length == 0
+ - nm_sec_domain_present.current.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+
+- name: Add user domain to aaa_user with check mode - idempotency works
+ cisco.aci.aci_aaa_user_domain:
+ <<: *cm_sec_domain_present
+ check_mode: true
+ register: cm_idempotency_sec_domain_present
+
+- name: Idempotency assertions check for add user domain to aaa_user with check mode
+ assert:
+ that:
+ - cm_idempotency_sec_domain_present is not changed
+ - cm_idempotency_sec_domain_present.current | length == 1
+ - cm_idempotency_sec_domain_present.previous | length == 1
+ - cm_idempotency_sec_domain_present.current.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+ - cm_idempotency_sec_domain_present.previous.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+
+- name: Add user domain to aaa_user with normal mode - idempotency works
+ cisco.aci.aci_aaa_user_domain:
+ <<: *nm_sec_domain_present
+ register: idempotency_sec_domain_present
+
+- name: Idempotency assertions check for add user domain to aaa_user with normal mode
+ assert:
+ that:
+ - idempotency_sec_domain_present is not changed
+ - idempotency_sec_domain_present.current | length == 1
+ - idempotency_sec_domain_present.previous | length == 1
+ - idempotency_sec_domain_present.current.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+ - idempotency_sec_domain_present.previous.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+
+- name: Add list of user domains to a aaa_user
+ cisco.aci.aci_aaa_user_domain:
+ <<: *aci_info
+ name: "{{ item.name }}"
+ aaa_user: ansible
+ state: present
+ with_items:
+ - name: all
+ - name: mgmt
+
+# QUERY A USER DOMAIN
+- name: Query a user domain from a aaa_user
+ cisco.aci.aci_aaa_user_domain:
+ <<: *aci_info
+ name: anstest-security-domain
+ aaa_user: ansible
+ state: query
+ register: query_anstest_sec_domain
+
+- name: Assertions check for query a user domain from a aaa_user
+ assert:
+ that:
+ - query_anstest_sec_domain is not changed
+ - query_anstest_sec_domain.current | length == 1
+ - query_anstest_sec_domain.current.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+
+# QUERY ALL USER DOMAINS
+- name: Query all user domains from a aaa_user
+ cisco.aci.aci_aaa_user_domain:
+ <<: *aci_info
+ aaa_user: ansible
+ state: query
+ register: query_aaa_user_domains
+
+- name: Assertions check for query all user domains from a aaa_user
+ assert:
+ that:
+ - query_aaa_user_domains is not changed
+ - query_aaa_user_domains.current | length == 1
+ - query_aaa_user_domains.current.0.aaaUser.children | length == 4
+
+- name: Query all user domains
+ cisco.aci.aci_aaa_user_domain:
+ <<: *aci_info
+ state: query
+ register: query_all_aaa_user_domains
+
+- name: Assertions check for query all user domains
+ assert:
+ that:
+ - query_all_aaa_user_domains is not changed
+ - query_all_aaa_user_domains.current | length >= 3
+
+# REMOVE USER DOMAIN
+- name: Remove user domain from a aaa_user with check mode
+ cisco.aci.aci_aaa_user_domain: &cm_sec_domain_absent
+ <<: *nm_sec_domain_present
+ state: absent
+ check_mode: true
+ register: cm_sec_domain_absent
+
+- name: Assertions check for removing user domain from a aaa_user with check mode
+ assert:
+ that:
+ - cm_sec_domain_absent is changed
+ - cm_sec_domain_absent.current | length == 1
+ - cm_sec_domain_absent.current.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+ - cm_sec_domain_absent.previous | length == 1
+ - cm_sec_domain_absent.previous.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+
+- name: Remove user domain from a aaa_user with normal mode
+ cisco.aci.aci_aaa_user_domain: &nm_sec_domain_absent
+ <<: *cm_sec_domain_absent
+ state: absent
+ register: nm_sec_domain_absent
+
+- name: Assertions check for removing user domain from a aaa_user with normal mode
+ assert:
+ that:
+ - nm_sec_domain_absent is changed
+ - nm_sec_domain_absent.current == []
+ - nm_sec_domain_absent.previous | length == 1
+ - nm_sec_domain_absent.previous.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+
+- name: Remove user domain from a aaa_user with normal mode - idempotency works
+ cisco.aci.aci_aaa_user_domain:
+ <<: *nm_sec_domain_absent
+ state: absent
+ check_mode: true
+ register: idempotency_sec_domain_absent
+
+- name: Idempotency assertions check for removing user domain
+ assert:
+ that:
+ - idempotency_sec_domain_absent is not changed
+ - idempotency_sec_domain_absent.current == []
+ - idempotency_sec_domain_absent.previous == []
+
+# Cleanup part
+- name: Remove a aaa_user
+ cisco.aci.aci_aaa_user:
+ <<: *user_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml
new file mode 100644
index 000000000..4a4d34017
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_role/tasks/main.yml
@@ -0,0 +1,336 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, Tim Cragg (timcragg) <tcragg@cisco.com>
+# Copyright: (c) 2022, Sabari Jaganathan (@sajagana)
+# Copyright: (c) 2017, Dag Wieers (dagwieers) <dag@wieers.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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove any pre-existing user
+ cisco.aci.aci_aaa_user:
+ <<: *aci_info
+ aaa_user: ansible
+ state: absent
+
+# ADD USER
+- name: Add a aaa_user
+ cisco.aci.aci_aaa_user: &user_present
+ <<: *aci_info
+ aaa_user: ansible
+ aaa_password: 12!Ab:cD!34
+ description: Ansible test user
+ email: ansible@ansible.lan
+ enabled: true
+ expiration: never
+ expires: false
+ first_name: Ansible
+ last_name: User
+ phone: 1-234-555-678
+ register: add_user
+
+# ADD SECURITY DOMAINS
+- name: Ensure anstest-security-domain exists
+ cisco.aci.aci_aaa_domain:
+ <<: *aci_info
+ name: anstest-security-domain
+ state: present
+
+- name: Ensure anstest-security-domain-1 exists
+ cisco.aci.aci_aaa_domain:
+ <<: *aci_info
+ name: anstest-security-domain-1
+ state: present
+
+# ADD USER DOMAIN
+- name: Add "anstest-security-domain" user domain to aaa_user
+ cisco.aci.aci_aaa_user_domain: &sec_domain_present
+ <<: *aci_info
+ name: anstest-security-domain
+ aaa_user: ansible
+ state: present
+
+- name: Add "anstest-security-domain-1" user domain to aaa_user
+ cisco.aci.aci_aaa_user_domain: &sec_domain1_present
+ <<: *aci_info
+ name: anstest-security-domain-1
+ aaa_user: ansible
+ state: present
+
+# Test Part
+# ADD USER ROLE
+- name: Add user role to "anstest-security-domain" user domain with check mode
+ cisco.aci.aci_aaa_user_role: &cm_user_role_present
+ <<: *aci_info
+ aaa_user: ansible
+ user_domain: anstest-security-domain
+ name: admin
+ privilege_type: write
+ state: present
+ check_mode: true
+ register: cm_user_role_present
+
+- name: Assertions check for add user role to "anstest-security-domain" with check mode
+ assert:
+ that:
+ - cm_user_role_present is changed
+ - cm_user_role_present.current | length == 0
+ - cm_user_role_present.previous | length == 0
+ - cm_user_role_present.sent.aaaUserRole.attributes.name == 'admin'
+ - cm_user_role_present.sent.aaaUserRole.attributes.privType == 'writePriv'
+
+- name: Add user role to "anstest-security-domain" user domain with normal mode
+ cisco.aci.aci_aaa_user_role: &nm_user_role_present
+ <<: *cm_user_role_present
+ register: nm_user_role_present
+
+- name: Assertions check for add user role to "anstest-security-domain" with normal mode
+ assert:
+ that:
+ - nm_user_role_present is changed
+ - nm_user_role_present.current | length == 1
+ - nm_user_role_present.previous | length == 0
+ - nm_user_role_present.current.0.aaaUserRole.attributes.name == 'admin'
+ - nm_user_role_present.current.0.aaaUserRole.attributes.privType == 'writePriv'
+
+- name: Add user role to "anstest-security-domain" user domain with check mode - idempotency works
+ cisco.aci.aci_aaa_user_role:
+ <<: *nm_user_role_present
+ check_mode: true
+ register: cm_idempotency_user_role_present
+
+- name: Idempotency assertions check for add user role to "anstest-security-domain" check mode
+ assert:
+ that:
+ - cm_idempotency_user_role_present is not changed
+ - cm_idempotency_user_role_present.previous | length == 1
+ - cm_idempotency_user_role_present.current | length == 1
+ - cm_idempotency_user_role_present.current.0.aaaUserRole.attributes.name == 'admin'
+ - cm_idempotency_user_role_present.current.0.aaaUserRole.attributes.privType == 'writePriv'
+ - cm_idempotency_user_role_present.previous.0.aaaUserRole.attributes.name == 'admin'
+ - cm_idempotency_user_role_present.previous.0.aaaUserRole.attributes.privType == 'writePriv'
+
+- name: Add user role to "anstest-security-domain" user domain with normal mode - idempotency works
+ cisco.aci.aci_aaa_user_role:
+ <<: *nm_user_role_present
+ register: idempotency_user_role_present
+
+- name: Idempotency assertions check for add user role to "anstest-security-domain"
+ assert:
+ that:
+ - idempotency_user_role_present is not changed
+ - idempotency_user_role_present.previous | length == 1
+ - idempotency_user_role_present.current | length == 1
+ - idempotency_user_role_present.current.0.aaaUserRole.attributes.name == 'admin'
+ - idempotency_user_role_present.current.0.aaaUserRole.attributes.privType == 'writePriv'
+ - idempotency_user_role_present.previous.0.aaaUserRole.attributes.name == 'admin'
+ - idempotency_user_role_present.previous.0.aaaUserRole.attributes.privType == 'writePriv'
+
+- name: Add user role to "anstest-security-domain-1" user domain
+ cisco.aci.aci_aaa_user_role:
+ <<: *aci_info
+ aaa_user: ansible
+ user_domain: anstest-security-domain-1
+ name: admin
+ state: present
+ register: user_role_present_sec_domain1
+
+- name: Assertions check for add a user role to "anstest-security-domain-1"
+ assert:
+ that:
+ - user_role_present_sec_domain1 is changed
+ - user_role_present_sec_domain1.current | length == 1
+ - user_role_present_sec_domain1.previous | length == 0
+ - user_role_present_sec_domain1.current.0.aaaUserRole.attributes.name == 'admin'
+ - user_role_present_sec_domain1.current.0.aaaUserRole.attributes.privType == 'readPriv'
+
+# UPDATE USER ROLE
+- name: Update user role to "anstest-security-domain" user domain with check mode
+ cisco.aci.aci_aaa_user_role:
+ <<: *nm_user_role_present
+ privilege_type: read
+ check_mode: true
+ register: cm_update_user_role_present
+
+- name: Assertions check for update user role to "anstest-security-domain" with check mode
+ assert:
+ that:
+ - cm_update_user_role_present is changed
+ - cm_update_user_role_present.current | length == 1
+ - cm_update_user_role_present.previous | length == 1
+ - cm_update_user_role_present.sent.aaaUserRole.attributes.privType == 'readPriv'
+
+- name: Update user role to "anstest-security-domain" user domain with normal mode
+ cisco.aci.aci_aaa_user_role:
+ <<: *nm_user_role_present
+ privilege_type: read
+ register: update_user_role_present
+
+- name: Assertions check for update user role to "anstest-security-domain" with normal mode
+ assert:
+ that:
+ - update_user_role_present is changed
+ - update_user_role_present.current | length == 1
+ - update_user_role_present.previous | length == 1
+ - update_user_role_present.current.0.aaaUserRole.attributes.name == 'admin'
+ - update_user_role_present.current.0.aaaUserRole.attributes.privType == 'readPriv'
+
+- name: Add list of user roles to a user domain
+ cisco.aci.aci_aaa_user_role:
+ <<: *aci_info
+ aaa_user: ansible
+ user_domain: anstest-security-domain
+ name: "{{ item.name }}"
+ privilege_type: "{{ item.privilege_type }}"
+ state: present
+ with_items:
+ - name: aaa
+ privilege_type: write
+ - name: access-admin
+ privilege_type: write
+ - name: ops
+ privilege_type: write
+
+# QUERY USER ROLE
+- name: Query a user role from "anstest-security-domain-1" user domain
+ cisco.aci.aci_aaa_user_role:
+ <<: *aci_info
+ user_domain: anstest-security-domain-1
+ name: admin
+ state: query
+ register: query_user_role_from_sec_domain
+
+- name: Assertions check for query a user role from "anstest-security-domain-1" user domain
+ assert:
+ that:
+ - query_user_role_from_sec_domain is not changed
+ - query_user_role_from_sec_domain.current | length == 1
+ - query_user_role_from_sec_domain.current.0.aaaUserDomain.children | length == 1
+ - query_user_role_from_sec_domain.current.0.aaaUserDomain.children.0.aaaUserRole.attributes.name == 'admin'
+ - query_user_role_from_sec_domain.current.0.aaaUserDomain.children.0.aaaUserRole.attributes.privType == 'readPriv'
+
+# QUERY ALL USER ROLES
+- name: Query all user roles from "anstest-security-domain" user domain
+ cisco.aci.aci_aaa_user_role:
+ <<: *aci_info
+ aaa_user: ansible
+ user_domain: anstest-security-domain
+ state: query
+ register: query_all_user_roles_of_sec_domain
+
+- name: Assertions check for query all user roles from "anstest-security-domain" user domain
+ assert:
+ that:
+ - query_all_user_roles_of_sec_domain is not changed
+ - query_all_user_roles_of_sec_domain.current | length == 1
+ - query_all_user_roles_of_sec_domain.current.0.aaaUserDomain.attributes.name == 'anstest-security-domain'
+ - query_all_user_roles_of_sec_domain.current.0.aaaUserDomain.children | length == 4
+
+- name: Query all user roles from a user
+ cisco.aci.aci_aaa_user_role:
+ <<: *aci_info
+ aaa_user: ansible
+ state: query
+ register: query_all_user_roles_from_a_user
+
+- name: Assertions check for query all user roles from a user
+ assert:
+ that:
+ - query_all_user_roles_from_a_user is not changed
+ - query_all_user_roles_from_a_user.current | length == 1
+ - query_all_user_roles_from_a_user.current.0.aaaUser.attributes.name == 'ansible'
+ - query_all_user_roles_from_a_user.current.0.aaaUser.children | length == 3 # count of user domains including common
+
+- name: Query all user roles
+ cisco.aci.aci_aaa_user_role:
+ <<: *aci_info
+ state: query
+ register: query_all_user_roles
+
+- name: Assertions check for query all user roles
+ assert:
+ that:
+ - query_all_user_roles is not changed
+ - query_all_user_roles.current | length >= 6 # count of user roles including common sec domain user role
+
+# REMOVE USER ROLE
+- name: Remove user role from a user domain with check mode
+ cisco.aci.aci_aaa_user_role: &cm_user_role_absent
+ <<: *aci_info
+ aaa_user: ansible
+ user_domain: anstest-security-domain-1
+ name: admin
+ state: absent
+ check_mode: true
+ register: cm_user_role_absent
+
+- name: Assertions check for removing a user role from "anstest-security-domain-1" with check mode
+ assert:
+ that:
+ - cm_user_role_absent is changed
+ - cm_user_role_absent.current | length == 1
+ - cm_user_role_absent.current.0.aaaUserRole.attributes.name == 'admin'
+ - cm_user_role_absent.current.0.aaaUserRole.attributes.privType == 'readPriv'
+ - cm_user_role_absent.previous | length == 1
+ - cm_user_role_absent.previous.0.aaaUserRole.attributes.name == 'admin'
+ - cm_user_role_absent.previous.0.aaaUserRole.attributes.privType == 'readPriv'
+
+- name: Remove user role from a user domain with normal mode
+ cisco.aci.aci_aaa_user_role: &nm_user_role_absent
+ <<: *cm_user_role_absent
+ register: nm_user_role_absent
+
+- name: Assertions check for removing a user role from "anstest-security-domain-1" with normal mode
+ assert:
+ that:
+ - nm_user_role_absent is changed
+ - nm_user_role_absent.current == []
+ - nm_user_role_absent.previous | length == 1
+ - nm_user_role_absent.previous.0.aaaUserRole.attributes.name == 'admin'
+ - nm_user_role_absent.previous.0.aaaUserRole.attributes.privType == 'readPriv'
+
+- name: Remove user role from a user domain with normal mode - idempotency works
+ cisco.aci.aci_aaa_user_role:
+ <<: *nm_user_role_absent
+ register: idempotency_user_role_absent
+
+- name: Idempotency assertions check for removing a user role from "anstest-security-domain-1"
+ assert:
+ that:
+ - idempotency_user_role_absent is not changed
+ - idempotency_user_role_absent.current == []
+ - idempotency_user_role_absent.previous == []
+
+# Cleanup part
+- name: Remove aaa_user "ansible"
+ cisco.aci.aci_aaa_user:
+ <<: *user_present
+ state: absent
+
+- name: Remove anstest-security-domain domain
+ cisco.aci.aci_aaa_domain:
+ <<: *aci_info
+ name: anstest-security-domain
+ state: absent
+
+- name: Remove anstest-security-domain-1 domain
+ cisco.aci.aci_aaa_domain:
+ <<: *aci_info
+ name: anstest-security-domain-1
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/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_port_block_to_access_port/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml
new file mode 100644
index 000000000..38bda95c8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml
@@ -0,0 +1,261 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish <ssrish@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)
+
+- 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
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensuring Interface Policy Leaf profile does not exist
+ cisco.aci.aci_interface_policy_leaf_profile: &aci_interface_policy_leaf_profile_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
+ state: absent
+ leaf_interface_profile: leafintprftest
+ register: leaf_profile_present
+
+ - name: Ensuring Interface Policy Leaf profile does not exist on fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+
+ - name: Ensuring Interface Policy Leaf profile exists for kick off
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+ leaf_interface_profile: leafintprftest
+ state: present
+
+ - name: Ensuring Interface Policy Leaf profile exists for kick off
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ state: present
+
+ - name: Ensure Interface Access Port Selector exists for kick of
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile: &aci_access_port_to_interface_policy_leaf_profile_present
+ <<: *aci_interface_policy_leaf_profile_absent
+ access_port_selector: anstest_accessportselector
+ state: present
+
+ - name: Ensure Interface Access Port Selector exists for kick of
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+
+ # TODO: Ensure that leaf Policy Group Exists (module missing) (infra:AccPortGrp)
+ # Ensure block does not exist.
+ - name: Bind an Access Port Block to an Interface Access Port Selector - check mode works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ leaf_port_blk: anstest_leafportblkname
+ state: absent
+
+ - name: Bind an Access Port Block to an Interface Access Port Selector - check mode works
+ cisco.aci.aci_access_port_block_to_access_port: &aci_access_port_block_to_access_port_present
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ leaf_port_blk: anstest_leafportblkname
+ leaf_port_blk_description: anstest_leafportblkdesc
+ fromPort: 13
+ toPort: 16
+ check_mode: true
+ register: accessportblock_to_accessport_check_mode_present
+
+ - name: Bind an Access Port Block to an Interface Access Port Selector - creation works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ register: accessportblock_to_accessport_present
+
+ - name: Bind an Access Port Block to an Interface Access Port Selector - 2
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ leaf_port_blk: anstest_leafportblkname_2
+ leaf_port_blk_description: anstest_leafportblkdesc
+ fromPort: 25
+ toPort: 26
+ register: accessportblock_to_accessport_check_mode_present_2
+
+ - name: Bind an Access Port Block to an Interface Access Port Selector - idempotency works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ register: accessportblock_to_accessport_idempotent
+
+ - name: Bind an Access Port Block to an Interface Access Port Selector - update works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ toPort: 15
+ register: accessportblock_to_accessport_update
+
+ - name: Associate an access port block (single port) to an interface selector on a fex - creation works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+ leaf_port_blk_description: anstest_leafportblkdesc_fex
+ leaf_port_blk: fex_blk
+ fromPort: 14
+ toPort: 17
+ register: accessportblock_to_accessport_present_fex
+
+ - name: Associate an access port block (single port) to an interface selector on a fex - creation works 2
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+ leaf_port_blk_description: anstest_leafportblkdesc_fex_2
+ leaf_port_blk: fex_blk_2
+ fromPort: 20
+ toPort: 21
+ register: accessportblock_to_accessport_present_fex_2
+
+
+ - name: Associate an access port block (single port) to an interface selector on a fex - idempotency works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+ leaf_port_blk_description: anstest_leafportblkdesc_fex
+ leaf_port_blk: fex_blk
+ fromPort: 14
+ toPort: 17
+ register: accessportblock_to_accessport_present_fex_idemp
+
+ - name: Associate an access port block (single port) to an interface selector on a fex - update works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+ leaf_port_blk_description: anstest_leafportblkdesc_fex
+ leaf_port_blk: fex_blk
+ fromPort: 23
+ toPort: 24
+ register: accessportblock_to_accessport_present_fex_update
+
+ # TODO: also test for errors
+ - name: present assertions - create / indempotency / update works
+ assert:
+ that:
+ - accessportblock_to_accessport_check_mode_present is changed
+ - accessportblock_to_accessport_present is changed
+ - accessportblock_to_accessport_present.current.0.infraPortBlk.attributes.annotation == 'orchestrator:ansible'
+ - accessportblock_to_accessport_present.previous == []
+ - accessportblock_to_accessport_present.sent.infraPortBlk.attributes.descr == 'anstest_leafportblkdesc'
+ - accessportblock_to_accessport_present.sent.infraPortBlk.attributes.name == 'anstest_leafportblkname'
+ - accessportblock_to_accessport_present.sent.infraPortBlk.attributes.fromPort == '13'
+ - accessportblock_to_accessport_present.sent.infraPortBlk.attributes.toPort == '16'
+ - accessportblock_to_accessport_idempotent is not changed
+ - accessportblock_to_accessport_idempotent.sent == {}
+ - accessportblock_to_accessport_update is changed
+ - accessportblock_to_accessport_update.sent.infraPortBlk.attributes.toPort == '15'
+ - accessportblock_to_accessport_present_fex is changed
+ - accessportblock_to_accessport_present_fex_idemp is not changed
+ - accessportblock_to_accessport_present_fex.sent.infraPortBlk.attributes.descr == 'anstest_leafportblkdesc_fex'
+ - accessportblock_to_accessport_present_fex.sent.infraPortBlk.attributes.fromPort == '14'
+ - accessportblock_to_accessport_present_fex.sent.infraPortBlk.attributes.toPort == '17'
+ - accessportblock_to_accessport_present_fex_update.sent.infraPortBlk.attributes.toPort == '24'
+
+ - name: Query Specific port block and access_port_selector binding
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ state: query
+ register: binding_query
+
+ - name: Query Specific port block and access_port_selector binding fex
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_present
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+ leaf_port_blk: fex_blk
+ state: query
+ register: binding_query_fex
+
+ - name: query assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query_fex is not changed
+ - binding_query_fex.current | length >= 1
+ - binding_query.current | length >= 1
+ - '"api/mo/uni/infra/accportprof-leafintprftest/hports-anstest_accessportselector-typ-range/portblk-anstest_leafportblkname.json" in binding_query.url'
+
+ - name: Remove binding of Access Port Block and Interface Access Port Selector - check mode
+ cisco.aci.aci_access_port_block_to_access_port: &aci_access_port_block_to_access_port_absent
+ <<: *aci_access_port_block_to_access_port_present
+ state: absent
+ check_mode: true
+ register: accessportblock_to_accessport_check_mode_absent
+
+ - name: Remove binding of Access Port Block and Interface Access Port Selector - delete works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_absent
+ register: accessportblock_to_accessport_absent
+
+ - name: Remove binding of Access Port Block and Interface Access Port Selector - idempotency works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_absent
+ register: accessportblock_to_accessport_absent_idempotent
+
+ - name: Remove binding of Access Port Block and Interface Access Port Selector - check mode
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ #leaf_port_blk: anstest_leafportblkname
+ state: absent
+ ignore_errors: true
+ register: accessportblock_to_accessport_absent_missing_param
+
+ - name: Remove binding of Access Port Block and Interface Access Port Selector - delete works
+ cisco.aci.aci_access_port_block_to_access_port:
+ <<: *aci_access_port_block_to_access_port_absent
+ type: fex
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+ leaf_port_blk: fex_blk
+ state: absent
+ register: accessportblock_to_accessport_absent_fex
+
+
+ - name: absent assertions
+ assert:
+ that:
+ - accessportblock_to_accessport_check_mode_absent is changed
+ - accessportblock_to_accessport_check_mode_absent.previous != []
+ - accessportblock_to_accessport_absent is changed
+ - accessportblock_to_accessport_absent.previous == accessportblock_to_accessport_check_mode_absent.previous
+ - accessportblock_to_accessport_absent_idempotent is not changed
+ - accessportblock_to_accessport_absent_idempotent.previous == []
+ - accessportblock_to_accessport_absent_missing_param is failed
+ - 'accessportblock_to_accessport_absent_missing_param.msg == "state is absent but all of the following are missing: port_blk"'
+ - accessportblock_to_accessport_absent_fex is changed
+
+ - name: Ensuring Interface Policy Leaf profile does not exist
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+ leaf_interface_profile: leafintprftest
+
+ - name: Ensuring Interface Policy Leaf profile does not exist on fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+ type: fex
+ leaf_interface_profile: leafintprftest_fex \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_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_access_port_to_interface_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 000000000..2244e0b16
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,728 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish <ssrish@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)
+
+- 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 execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Remove Interface policy leaf profile - Cleanup
+ cisco.aci.aci_interface_policy_leaf_profile:
+ &aci_interface_policy_leaf_profile_absent
+ <<: *aci_info
+ leaf_interface_profile: leafintprftest
+ state: absent
+
+ - name: Remove Interface policy fex profile - Cleanup
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+ type: fex
+ leaf_interface_profile: fexintprftest
+ state: absent
+
+ - name: Ensuring bindings do not already exist
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ &aci_access_port_to_interface_policy_leaf_profile_absent
+ <<: *aci_info
+ leaf_interface_profile: leafintprftest
+ access_port_selector: anstest_accessportselector
+ state: absent
+
+ - name: Ensuring bindings do not already exist
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_absent
+ leaf_interface_profile: leafintprftest_fex
+ access_port_selector: anstest_accessportselector_fex
+ state: absent
+
+ - name: Ensuring Interface Policy Leaf profile exists for kick off
+ cisco.aci.aci_interface_policy_leaf_profile:
+ &aci_interface_policy_leaf_profile_present
+ <<: *aci_info
+ state: present
+ leaf_interface_profile: leafintprftest
+ register: leaf_profile_present
+
+ - name: Ensuring Interface Policy Fex profile exists for kick off
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_present
+ type: fex
+ leaf_interface_profile: fexintprftest
+
+ - name: Add a new fex policy group to the fexintprftest fex profile
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &fexintprftest_policy_group_present
+ <<: *aci_info
+ policy_group: fexintprftest
+ fex_profile: fexintprftest
+ state: present
+ register: fexintprftest_policy_group_present
+
+ - name: Assertions check for remove fex policy group from the fexintprftest fex profile
+ assert:
+ that:
+ - fexintprftest_policy_group_present is changed
+ - fexintprftest_policy_group_present.current | length == 1
+ - fexintprftest_policy_group_present.previous | length == 0
+ - fexintprftest_policy_group_present.current.0.infraFexBndlGrp.attributes.name == "fexintprftest"
+ - fexintprftest_policy_group_present.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-fexintprftest/fexbundle-fexintprftest"
+
+ # TODO: Ensure that leaf Policy Group Exists (module missing) (infra:AccPortGrp)
+
+ - name: Bind an Interface Access Port Selector to an Interface Policy Leaf Profile with a Policy Group - check mode works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ &aci_access_port_to_interface_policy_leaf_profile_present
+ <<: *aci_interface_policy_leaf_profile_present
+ access_port_selector: anstest_accessportselector
+ check_mode: true
+ register: accessport_to_intf_check_mode_present
+
+ - name: Bind an Interface Access Port Selector to an Interface Policy Leaf Profile with a Policy Group - creation works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ register: accessport_to_intf_present
+
+ - name: Bind an Interface Access Port Selector to an Interface Policy Leaf Profile with a Policy Group - idempotency works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ register: accessport_to_intf_idempotent
+
+ - name: Bind an Interface Access Port Selector to an Interface Policy Profile with a Policy Group - update works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ policy_group: anstest_policygroupname
+ register: accessport_to_intf_update
+
+ - name: Bind an Interface Access Port Selector to an Interface Policy Fex Profile with a Policy Group - creation works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ type: fex
+ access_port_selector: anstest_fex_accessportselector
+ leaf_interface_profile: fexintprftest
+ register: accessport_to_intf_present_fex
+
+ - name: Bind an Interface Access Port Selector to an Interface Policy Fex Profile with a Policy Group - idempotency works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ type: fex
+ access_port_selector: anstest_fex_accessportselector
+ leaf_interface_profile: fexintprftest
+ register: accessport_to_intf_idempotent_fex
+
+ - name: Bind an Interface Access Port Selector to an Interface Policy Fex Profile with a Policy Group - update works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ policy_group: anstest_fex_policygroupname
+ access_port_selector: anstest_fex_accessportselector
+ type: fex
+ leaf_interface_profile: fexintprftest
+ register: accessport_to_intf_update_fex
+
+ # TODO: also test for errors
+ - name: present assertions
+ assert:
+ that:
+ - accessport_to_intf_check_mode_present is changed
+ - accessport_to_intf_present is changed
+ - accessport_to_intf_present.current.0.infraHPortS.attributes.annotation == 'orchestrator:ansible'
+ - accessport_to_intf_present.previous == []
+ - accessport_to_intf_present.sent.infraHPortS.attributes.name == 'anstest_accessportselector'
+ - accessport_to_intf_idempotent is not changed
+ - accessport_to_intf_idempotent.sent == {}
+ - accessport_to_intf_update is changed
+ - accessport_to_intf_update.sent.infraHPortS.attributes == {}
+ - accessport_to_intf_update.sent.infraHPortS.children[0].infraRsAccBaseGrp.attributes.tDn == 'uni/infra/funcprof/accportgrp-anstest_policygroupname'
+ - accessport_to_intf_present_fex is changed
+ - accessport_to_intf_present_fex.previous == []
+ - accessport_to_intf_present_fex.sent.infraHPortS.attributes.name == 'anstest_fex_accessportselector'
+ - accessport_to_intf_idempotent_fex is not changed
+ - accessport_to_intf_idempotent_fex.sent == {}
+ - accessport_to_intf_update_fex is changed
+ - accessport_to_intf_update_fex.sent.infraHPortS.children[0].infraRsAccBaseGrp.attributes.tDn == 'uni/infra/funcprof/accportgrp-anstest_fex_policygroupname'
+
+ - name: Query Specific access_port_selector and leaf_interface_profile binding
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_present
+ access_port_selector: anstest_accessportselector # "{{ fake_var | default(omit) }}" ?
+ state: query
+ output_level: debug
+ register: binding_query
+
+ - name: Query Specific access_port_selector and fex_interface_profile binding
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_present
+ type: fex
+ access_port_selector: anstest_fex_accessportselector
+ leaf_interface_profile: fexintprftest
+ state: query
+ output_level: debug
+ register: binding_query_fex
+
+ - name: present assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query_fex is not changed
+ - binding_query.current | length >= 1
+ - '"api/mo/uni/infra/accportprof-leafintprftest/hports-anstest_accessportselector-typ-range.json" in binding_query.url'
+
+ - name: Bind anstest_fex_accessportselector with fexintprftest - Fex Profile Policy Group
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_info
+ state: present
+ leaf_interface_profile: leafintprftest
+ fex_profile: fexintprftest
+ policy_group: fexintprftest
+ access_port_selector_name: anstest_fex_accessportselector
+ interface_type: fex_profile
+ from_port: 13
+ to_port: 13
+ port_blk: block2
+ fex_id: 105
+ register: bind_fexintprftest_policy_group
+
+ - name: Assertions check for bind anstest_fex_accessportselector with fexintprftest - Fex Profile Policy Group
+ assert:
+ that:
+ - bind_fexintprftest_policy_group is changed
+ - bind_fexintprftest_policy_group.previous | length == 0
+ - bind_fexintprftest_policy_group.current.0.infraHPortS.attributes.name == "anstest_fex_accessportselector"
+ - bind_fexintprftest_policy_group.current.0.infraHPortS.children.1.infraRsAccBaseGrp.attributes.fexId == "105"
+ - bind_fexintprftest_policy_group.current.0.infraHPortS.children.1.infraRsAccBaseGrp.attributes.tDn == "uni/infra/fexprof-fexintprftest/fexbundle-fexintprftest"
+
+ - name: Bind anstest_fex_accessportselector_2 without fex_profile
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_info
+ state: present
+ leaf_interface_profile: leafintprftest
+ policy_group: fexintprftest
+ access_port_selector_name: anstest_fex_accessportselector_2
+ interface_type: fex_profile
+ from_port: 14
+ to_port: 14
+ port_blk: block2
+ fex_id: 106
+ register: bind_fexintprftest_policy_group_2
+
+ - name: Assertions check for bind anstest_fex_accessportselector with fexintprftest - Fex Profile Policy Group
+ assert:
+ that:
+ - bind_fexintprftest_policy_group_2 is changed
+ - bind_fexintprftest_policy_group_2.previous | length == 0
+ - bind_fexintprftest_policy_group_2.current.0.infraHPortS.attributes.name == "anstest_fex_accessportselector_2"
+ - bind_fexintprftest_policy_group_2.current.0.infraHPortS.children.1.infraRsAccBaseGrp.attributes.fexId == "106"
+ - bind_fexintprftest_policy_group_2.current.0.infraHPortS.children.1.infraRsAccBaseGrp.attributes.tDn == "uni/infra/fexprof-fexintprftest/fexbundle-fexintprftest"
+
+ - name: Remove fex policy group from the fexintprftest fex profile
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ <<: *fexintprftest_policy_group_present
+ state: absent
+ register: fexintprftest_policy_group_absent
+
+ - name: Assertions check for remove fex policy group from the fexintprftest fex profile
+ assert:
+ that:
+ - fexintprftest_policy_group_absent is changed
+ - fexintprftest_policy_group_absent.current | length == 0
+ - fexintprftest_policy_group_absent.previous | length == 1
+ - fexintprftest_policy_group_absent.previous.0.infraFexBndlGrp.attributes.name == "fexintprftest"
+ - fexintprftest_policy_group_absent.previous.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-fexintprftest/fexbundle-fexintprftest"
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_absent
+ check_mode: true
+ register: accessport_to_intf_check_mode_absent
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - delete works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_absent
+ register: accessport_to_intf_absent
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - idempotency works
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_absent
+ register: accessport_to_intf_absent_idempotent
+
+ - name: Remove binding of interface access port selector and Interface Policy Fex Profile
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_absent
+ type: fex
+ access_port_selector: anstest_fex_accessportselector
+ leaf_interface_profile: fexintprftest
+ state: absent
+ register: accessport_to_intf_absent_fex
+
+ - name: absent assertions
+ assert:
+ that:
+ - accessport_to_intf_check_mode_absent is changed
+ - accessport_to_intf_absent_fex is changed
+ - accessport_to_intf_absent is changed
+ - accessport_to_intf_absent_idempotent is not changed
+
+ - name: Remove Interface policy fex profile - Cleanup
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+
+ - name: Remove Interface policy fex profile - Cleanup
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_absent
+ type: fex
+ leaf_interface_profile: fexintprftest
+ state: absent
+
+ - name: Add anstest_fex_port_channel - Interface Policy Leaf Profile with type Fex
+ cisco.aci.aci_interface_policy_leaf_profile: &anstest_fex_port_channel_present
+ <<: *aci_interface_policy_leaf_profile_present
+ type: fex
+ leaf_interface_profile: anstest_fex_port_channel
+
+ - name: Add policygroupname_link_fpc - Policy Group with lag type link
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ policy_group: policygroupname_link_fpc
+ lag_type: link
+ link_level_policy: link_level_policy
+ fibre_channel_interface_policy: fiber_channel_policy
+ state: present
+
+ - name: Bind anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - check mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile: &cm_fpc_present
+ <<: *anstest_fex_port_channel_present
+ interface_type: fex_port_channel
+ access_port_selector: anstest_fex_port_channel
+ policy_group: policygroupname_link_fpc
+ check_mode: true
+ register: cm_fpc_present
+
+ - name: Assertion check for bind anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - check mode
+ assert:
+ that:
+ - cm_fpc_present.current | length == 0
+ - cm_fpc_present.previous | length == 0
+ - cm_fpc_present.sent.infraHPortS.attributes.name == "anstest_fex_port_channel"
+ - cm_fpc_present.sent.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_link_fpc"
+
+ - name: Bind anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - normal mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile: &nm_fpc_present
+ <<: *cm_fpc_present
+ register: nm_fpc_present
+
+ - name: Assertion check for bind anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - normal mode
+ assert:
+ that:
+ - nm_fpc_present.current | length == 1
+ - nm_fpc_present.previous | length == 0
+ - nm_fpc_present.current.0.infraHPortS.attributes.name == "anstest_fex_port_channel"
+ - nm_fpc_present.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_link_fpc"
+ - nm_fpc_present.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+
+ - name: Remove anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - check mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile: &cm_fpc_absent
+ <<: *nm_fpc_present
+ state: absent
+ check_mode: true
+ register: cm_fpc_absent
+
+ - name: Assertion check for remove anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - check mode
+ assert:
+ that:
+ - cm_fpc_absent.current | length == 1
+ - cm_fpc_absent.previous | length == 1
+ - cm_fpc_absent.current.0.infraHPortS.attributes.name == "anstest_fex_port_channel"
+ - cm_fpc_absent.previous.0.infraHPortS.attributes.name == "anstest_fex_port_channel"
+ - cm_fpc_absent.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_link_fpc"
+ - cm_fpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_link_fpc"
+ - cm_fpc_absent.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+ - cm_fpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+
+ - name: Remove anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - normal mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *cm_fpc_absent
+ register: nm_fpc_absent
+
+ - name: Assertion check for remove anstest_fex_port_channel Access Port Selector with policygroupname_link_fpc Policy Group - normal mode
+ assert:
+ that:
+ - nm_fpc_absent.current | length == 0
+ - nm_fpc_absent.previous | length == 1
+ - nm_fpc_absent.previous.0.infraHPortS.attributes.name == "anstest_fex_port_channel"
+ - nm_fpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_link_fpc"
+ - nm_fpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+
+ - name: Add anstest_fex_vpc - Interface Policy Leaf Profile with type Fex
+ cisco.aci.aci_interface_policy_leaf_profile: &anstest_fex_vpc
+ <<: *aci_interface_policy_leaf_profile_present
+ type: fex
+ leaf_interface_profile: anstest_fex_vpc
+ register: anstest_fex_vpc_present
+
+ - name: Assertion check for add anstest_fex_vpc - Interface Policy Leaf Profile with type Fex
+ assert:
+ that:
+ - anstest_fex_vpc_present.current | length == 1
+ - anstest_fex_vpc_present.current.0.infraFexP.attributes.name == "anstest_fex_vpc"
+ - anstest_fex_vpc_present.current.0.infraFexP.attributes.dn == "uni/infra/fexprof-anstest_fex_vpc"
+
+ - name: Add policygroupname_node_fvpc - Policy Group with lag type node
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ policy_group: policygroupname_node_fvpc
+ lag_type: node
+ link_level_policy: link_level_policy
+ fibre_channel_interface_policy: fiber_channel_policy
+ state: present
+ register: policygroupname_node_fvpc_present
+
+ - name: Assertion check for add policygroupname_node_fvpc - Policy Group with lag type node
+ assert:
+ that:
+ - policygroupname_node_fvpc_present.current | length == 1
+ - policygroupname_node_fvpc_present.current.0.infraAccBndlGrp.attributes.name == "policygroupname_node_fvpc"
+ - policygroupname_node_fvpc_present.current.0.infraAccBndlGrp.attributes.lagT == "node"
+
+ - name: Bind anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - check mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ &cm_fex_vpc_present
+ <<: *anstest_fex_vpc
+ interface_type: fex_vpc
+ access_port_selector: anstest_fex_vpc
+ policy_group: policygroupname_node_fvpc
+ check_mode: true
+ register: cm_fex_vpc_present
+
+ - name: Assertion check for bind anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - check mode
+ assert:
+ that:
+ - cm_fex_vpc_present.current | length == 0
+ - cm_fex_vpc_present.previous | length == 0
+ - cm_fex_vpc_present.sent.infraHPortS.attributes.name == "anstest_fex_vpc"
+ - cm_fex_vpc_present.sent.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_node_fvpc"
+
+ - name: Bind anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - normal mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *cm_fex_vpc_present
+ register: nm_fex_vpc_present
+
+ - name: Assertion check for bind anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - normal mode
+ assert:
+ that:
+ - nm_fex_vpc_present.current | length == 1
+ - nm_fex_vpc_present.previous | length == 0
+ - nm_fex_vpc_present.current.0.infraHPortS.attributes.name == "anstest_fex_vpc"
+ - nm_fex_vpc_present.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+ - nm_fex_vpc_present.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_node_fvpc"
+
+ - name: Remove anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - check mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile: &cm_fex_vpc_absent
+ <<: *cm_fex_vpc_present
+ state: absent
+ check_mode: true
+ register: cm_fex_vpc_absent
+
+ - name: Assertion check for remove anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - check mode
+ assert:
+ that:
+ - cm_fex_vpc_absent.current | length == 1
+ - cm_fex_vpc_absent.previous | length == 1
+ - cm_fex_vpc_absent.current.0.infraHPortS.attributes.name == "anstest_fex_vpc"
+ - cm_fex_vpc_absent.previous.0.infraHPortS.attributes.name == "anstest_fex_vpc"
+ - cm_fex_vpc_absent.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+ - cm_fex_vpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+ - cm_fex_vpc_absent.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_node_fvpc"
+ - cm_fex_vpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_node_fvpc"
+
+ - name: Remove anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - normal mode
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *cm_fex_vpc_absent
+ register: nm_fex_vpc_absent
+
+ - name: Assertion check for remove anstest_fex_vpc Access Port Selector with policygroupname_node_fvpc Policy Group - normal mode
+ assert:
+ that:
+ - nm_fex_vpc_absent.current | length == 0
+ - nm_fex_vpc_absent.previous | length == 1
+ - nm_fex_vpc_absent.previous.0.infraHPortS.attributes.name == "anstest_fex_vpc"
+ - nm_fex_vpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "101"
+ - nm_fex_vpc_absent.previous.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/funcprof/accbundle-policygroupname_node_fvpc"
+
+ # Removing profiles
+ - name: Remove anstest_fex_vpc - Interface Policy Leaf Profile with type Fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *anstest_fex_vpc
+ state: absent
+ register: anstest_fex_vpc_absent
+
+ - name: Assertion check for remove anstest_fex_vpc - Interface Policy Leaf Profile with type Fex
+ assert:
+ that:
+ - anstest_fex_vpc_absent.current | length == 0
+ - anstest_fex_vpc_absent.previous | length == 1
+ - anstest_fex_vpc_absent.previous.0.infraFexP.attributes.name == "anstest_fex_vpc"
+
+ - name: Remove anstest_fex_port_channel - Interface Policy Leaf Profile with type Fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *anstest_fex_port_channel_present
+ state: absent
+ register: anstest_fex_port_channel_absent
+
+ - name: Assertion check for remove anstest_fex_port_channel - Interface Policy Leaf Profile with type Fex
+ assert:
+ that:
+ - anstest_fex_port_channel_absent.current | length == 0
+ - anstest_fex_port_channel_absent.previous | length == 1
+ - anstest_fex_port_channel_absent.previous.0.infraFexP.attributes.name == "anstest_fex_port_channel"
+
+ - name: Ensure anstest_leaf_profile interface does not exists
+ cisco.aci.aci_interface_policy_leaf_profile: &anstest_leaf_profile_absent
+ <<: *aci_info
+ type: leaf
+ leaf_interface_profile: anstest_leaf_profile
+ state: absent
+ register: anstest_leaf_profile_absent
+
+ - name: Assertion check for ensure anstest_leaf_profile interface does not exists
+ assert:
+ that:
+ - anstest_leaf_profile_absent.current | length == 0
+
+ - name: Ensure anstest_fex_profile interface does not exists
+ cisco.aci.aci_interface_policy_leaf_profile: &anstest_fex_profile_absent
+ <<: *aci_info
+ type: fex
+ leaf_interface_profile: anstest_fex_profile
+ state: absent
+ register: anstest_fex_profile_absent
+
+ - name: Assertion check for ensure anstest_fex_profile interface does not exists
+ assert:
+ that:
+ - anstest_fex_profile_absent.current | length == 0
+
+ - name: Ensure temp_anstest_fex_profile interface does not exists
+ cisco.aci.aci_interface_policy_leaf_profile: &temp_anstest_fex_profile_absent
+ <<: *aci_info
+ type: fex
+ leaf_interface_profile: temp_anstest_fex_profile
+ state: absent
+ register: temp_anstest_fex_profile_absent
+
+ - name: Assertion check for ensure temp_anstest_fex_profile interface does not exists
+ assert:
+ that:
+ - temp_anstest_fex_profile_absent.current | length == 0
+
+ - name: Add a new anstest_leaf_profile with profile type leaf
+ cisco.aci.aci_interface_policy_leaf_profile: &anstest_leaf_profile_present
+ <<: *anstest_leaf_profile_absent
+ state: present
+ register: anstest_leaf_profile_present
+
+ - name: Assertion check for add a new anstest_leaf_profile with profile type leaf
+ assert:
+ that:
+ - anstest_leaf_profile_present is changed
+ - anstest_leaf_profile_present.current | length == 1
+ - anstest_leaf_profile_present.previous | length == 0
+ - anstest_leaf_profile_present.current.0.infraAccPortP.attributes.name == "anstest_leaf_profile"
+ - anstest_leaf_profile_present.current.0.infraAccPortP.attributes.dn == "uni/infra/accportprof-anstest_leaf_profile"
+
+ - name: Add a new anstest_fex_profile with profile type fex
+ cisco.aci.aci_interface_policy_leaf_profile: &anstest_fex_profile_present
+ <<: *anstest_fex_profile_absent
+ state: present
+ register: anstest_fex_profile_present
+
+ - name: Assertion check for add a new anstest_fex_profile with profile type fex
+ assert:
+ that:
+ - anstest_fex_profile_present is changed
+ - anstest_fex_profile_present.current | length == 1
+ - anstest_fex_profile_present.previous | length == 0
+ - anstest_fex_profile_present.current.0.infraFexP.attributes.name == "anstest_fex_profile"
+ - anstest_fex_profile_present.current.0.infraFexP.attributes.dn == "uni/infra/fexprof-anstest_fex_profile"
+
+ - name: Add a new temp_anstest_fex_profile with profile type fex
+ cisco.aci.aci_interface_policy_leaf_profile: &temp_anstest_fex_profile_present
+ <<: *temp_anstest_fex_profile_absent
+ state: present
+ register: temp_anstest_fex_profile_present
+
+ - name: Assertion check for add a new temp_anstest_fex_profile with profile type fex
+ assert:
+ that:
+ - temp_anstest_fex_profile_present is changed
+ - temp_anstest_fex_profile_present.current | length == 1
+ - temp_anstest_fex_profile_present.previous | length == 0
+ - temp_anstest_fex_profile_present.current.0.infraFexP.attributes.name == "temp_anstest_fex_profile"
+ - temp_anstest_fex_profile_present.current.0.infraFexP.attributes.dn == "uni/infra/fexprof-temp_anstest_fex_profile"
+
+ - name: Add a new policy_group with the same name of interface profile - temp_anstest_fex_profile
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &temp_anstest_fex_profile_policy_group_present
+ <<: *aci_info
+ policy_group: temp_anstest_fex_profile
+ fex_profile: temp_anstest_fex_profile
+ state: present
+ register: temp_anstest_fex_profile_policy_group_present
+
+ - name: Assertion check for add a new policy_group with the same name of interface profile - temp_anstest_fex_profile
+ assert:
+ that:
+ - temp_anstest_fex_profile_policy_group_present is changed
+ - temp_anstest_fex_profile_policy_group_present.current | length == 1
+ - temp_anstest_fex_profile_policy_group_present.previous | length == 0
+ - temp_anstest_fex_profile_policy_group_present.current.0.infraFexBndlGrp.attributes.name == "temp_anstest_fex_profile"
+ - temp_anstest_fex_profile_policy_group_present.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-temp_anstest_fex_profile/fexbundle-temp_anstest_fex_profile"
+
+ - name: Bind temp_anstest_fex_profile with anstest_fex_profile - Fex Profile Policy Group
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_info
+ leaf_interface_profile: anstest_fex_profile
+ policy_group: temp_anstest_fex_profile
+ access_port_selector_name: temp_anstest_fex_profile_access_port
+ interface_type: fex_profile
+ fex_id: 105
+ type: fex
+ state: present
+ register: temp_anstest_fex_profile_access_port_present
+ ignore_errors: true
+
+ - name: Assertion check for bind temp_anstest_fex_profile with anstest_fex_profile - Fex Profile Policy Group
+ assert:
+ that:
+ - temp_anstest_fex_profile_access_port_present.msg == "Invalid Configuration - interface_type fex_profile can not be configured with a profile of type fex"
+
+ - name: Remove temp_anstest_fex_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *temp_anstest_fex_profile_absent
+ register: remove_anstest_fex_profile_absent
+
+ - name: Assertion check for remove temp_anstest_fex_profile
+ assert:
+ that:
+ - remove_anstest_fex_profile_absent is changed
+ - remove_anstest_fex_profile_absent.current | length == 0
+ - remove_anstest_fex_profile_absent.previous | length == 1
+
+ - name: Add a new policy_group with the same name of interface profile - anstest_fex_profile
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &anstest_fex_profile_policy_group_present
+ <<: *aci_info
+ policy_group: anstest_fex_profile
+ fex_profile: anstest_fex_profile
+ state: present
+ register: anstest_fex_profile_policy_group_present
+
+ - name: Assertion check for add a new policy_group with the same name of interface profile - anstest_fex_profile
+ assert:
+ that:
+ - anstest_fex_profile_policy_group_present is changed
+ - anstest_fex_profile_policy_group_present.current | length == 1
+ - anstest_fex_profile_policy_group_present.previous | length == 0
+ - anstest_fex_profile_policy_group_present.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_profile"
+ - anstest_fex_profile_policy_group_present.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_profile"
+
+ - name: Bind anstest_leaf_profile with anstest_fex_profile - Fex Profile Policy Group
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ &anstest_leaf_profile_access_port_present
+ <<: *aci_info
+ leaf_interface_profile: anstest_leaf_profile
+ policy_group: anstest_fex_profile
+ access_port_selector_name: anstest_leaf_profile_access_port
+ interface_type: fex_profile
+ fex_id: 105
+ type: leaf
+ state: present
+ register: anstest_leaf_profile_access_port_present
+
+ - name: Assertion check for bind anstest_leaf_profile with anstest_fex_profile - Fex Profile Policy Group
+ assert:
+ that:
+ - anstest_leaf_profile_access_port_present is changed
+ - anstest_leaf_profile_access_port_present.current | length == 1
+ - anstest_leaf_profile_access_port_present.previous | length == 0
+ - anstest_leaf_profile_access_port_present.current.0.infraHPortS.attributes.name == "anstest_leaf_profile_access_port"
+ - anstest_leaf_profile_access_port_present.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.tDn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_profile"
+ - anstest_leaf_profile_access_port_present.current.0.infraHPortS.children.0.infraRsAccBaseGrp.attributes.fexId == "105"
+
+ - name: Bind anstest_leaf_profile with anstest_fex_profile with wrong fex_id
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_info
+ leaf_interface_profile: anstest_leaf_profile
+ policy_group: anstest_fex_profile
+ access_port_selector_name: anstest_leaf_profile_access_port
+ interface_type: fex_profile
+ fex_id: 999
+ type: leaf
+ state: present
+ ignore_errors: true
+ register: anstest_leaf_profile_access_port_wrong_fex_id
+
+ - name: Assertion check for bind anstest_leaf_profile with wrong fex_id
+ assert:
+ that:
+ - anstest_leaf_profile_access_port_wrong_fex_id.msg == "A valid FEX ID is between 101 to 199"
+
+ - name: Bind anstest_leaf_profile with anstest_fex_profile with no fex_id
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_info
+ leaf_interface_profile: anstest_leaf_profile
+ policy_group: anstest_fex_profile
+ access_port_selector_name: anstest_leaf_profile_access_port
+ interface_type: fex_profile
+ type: leaf
+ state: present
+ ignore_errors: true
+ register: anstest_leaf_profile_access_port_no_fex_id
+
+ - name: Assertion check for bind anstest_leaf_profile with no fex_id
+ assert:
+ that:
+ - anstest_leaf_profile_access_port_no_fex_id.msg == "The fex_id must not be None, when interface_type is fex_profile"
+
+ - name: Remove anstest_leaf_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *anstest_leaf_profile_absent
+ register: anstest_leaf_profile_cleanup
+
+ - name: Assertion check for remove anstest_leaf_profile
+ assert:
+ that:
+ - anstest_leaf_profile_cleanup is changed
+ - anstest_leaf_profile_cleanup.previous | length == 1
+ - anstest_leaf_profile_cleanup.current | length == 0
+
+ - name: Remove anstest_fex_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *anstest_fex_profile_absent
+ register: anstest_fex_profile_cleanup
+
+ - name: Assertion check for remove anstest_fex_profile
+ assert:
+ that:
+ - anstest_fex_profile_cleanup is changed
+ - anstest_fex_profile_cleanup.previous | length == 1
+ - anstest_fex_profile_cleanup.current | length == 0
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_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_access_span_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/tasks/main.yml
new file mode 100644
index 000000000..03c2e92c2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_dst_group/tasks/main.yml
@@ -0,0 +1,347 @@
+# 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
+
+- name: Query all access span destination groups
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+- name: Clean access span destination groups
+ cisco.aci.aci_access_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 access span destination group type epg ( check mode )
+ cisco.aci.aci_access_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 access span destination group type epg
+ cisco.aci.aci_access_span_dst_group:
+ <<: *add_ansible_group_1
+ register: nm_add_ansible_group_1
+
+- name: Add access span destination group type epg again
+ cisco.aci.aci_access_span_dst_group:
+ <<: *add_ansible_group_1
+ register: nm_add_ansible_group_1_again
+
+- name: Verify add access span destination group type epg
+ 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 access span destination group type epg
+ cisco.aci.aci_access_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 access span destination group type epg
+ cisco.aci.aci_access_span_dst_group:
+ <<: *change_ansible_group_1
+ register: change_ansible_group_1_again
+
+- name: Verify change access span destination group type epg
+ 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: Change access span destination group type epg path information (error)
+ cisco.aci.aci_access_span_dst_group:
+ <<: *add_ansible_group_1
+ destination_epg:
+ destination_ip: 10.0.0.2
+ source_ip: 10.0.2.2
+ tenant: ansible_test_2
+ ap: ansible_test_2
+ epg: ansible_test_2
+ register: error_on_path_change_ansible_group_1
+ ignore_errors: true
+
+- name: Verify change access span destination group type epg path information (error)
+ ansible.builtin.assert:
+ that:
+ - error_on_path_change_ansible_group_1.msg == "APIC Error 105{{':'}} Span source or destination relation target configuration cannot be dynamically modified"
+
+- name: Add access span destination group type access interface port
+ cisco.aci.aci_access_span_dst_group: &add_ansible_group_2
+ <<: *aci_info
+ destination_group: ansible_group_2
+ description: test span access interface port
+ access_interface:
+ pod: 1
+ node: 101
+ path: eth1/1
+ mtu: 1500
+ state: present
+ register: add_ansible_group_2
+
+- name: Add access span destination group type access interface direct port channel
+ cisco.aci.aci_access_span_dst_group: &add_ansible_group_3
+ <<: *aci_info
+ destination_group: ansible_group_3
+ description: test span access interface port channel
+ access_interface:
+ pod: 1
+ node: 101
+ path: test-PolGrp
+ state: present
+ register: add_ansible_group_3
+
+- name: Verify add access span destination groups type access interface port and direct port channel
+ ansible.builtin.assert:
+ that:
+ - add_ansible_group_2 is changed
+ - add_ansible_group_2.current.0.spanDestGrp.attributes.name == "ansible_group_2"
+ - add_ansible_group_2.current.0.spanDestGrp.attributes.descr == "test span access interface port"
+ - add_ansible_group_2.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_2"
+ - add_ansible_group_2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestPathEp.attributes.mtu == "1500"
+ - add_ansible_group_2.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[eth1/1]"
+ - add_ansible_group_3 is changed
+ - add_ansible_group_3.current.0.spanDestGrp.attributes.name == "ansible_group_3"
+ - add_ansible_group_3.current.0.spanDestGrp.attributes.descr == "test span access interface port channel"
+ - add_ansible_group_3.current.0.spanDestGrp.children.0.spanDest.attributes.name == "ansible_group_3"
+ - add_ansible_group_3.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestPathEp.attributes.mtu == "1518"
+ - add_ansible_group_3.current.0.spanDestGrp.children.0.spanDest.children.0.spanRsDestPathEp.attributes.tDn == "topology/pod-1/paths-101/pathep-[test-PolGrp]"
+
+# TEST QUERY DESTINATION GROUPS
+
+- name: Query one access span destination group
+ cisco.aci.aci_access_span_dst_group:
+ <<: *add_ansible_group_1
+ state: query
+ register: query_one
+
+- name: Query all access span destination group
+ cisco.aci.aci_access_span_dst_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.spanDestGrp.attributes.name == "ansible_group_1"
+ - query_all is not changed
+ - query_all.current | length >= 3 # greater or equal because there could be configuration present that is not access span but is returned in ( class based ) query all
+
+# TEST REMOVAL DESTINATION GROUPS
+
+- name: Remove access span destination group type epg ( check mode )
+ cisco.aci.aci_access_span_dst_group: &remove_ansible_group_1
+ <<: *add_ansible_group_1
+ state: absent
+ check_mode: true
+ register: cm_remove_ansible_group_1
+
+- name: Remove access span destination group type epg
+ cisco.aci.aci_access_span_dst_group:
+ <<: *remove_ansible_group_1
+ register: nm_remove_ansible_group_1
+
+- name: Remove access span destination group type epg again
+ cisco.aci.aci_access_span_dst_group:
+ <<: *remove_ansible_group_1
+ register: nm_remove_ansible_group_1_again
+
+- name: Remove access span destination group type access interface port
+ cisco.aci.aci_access_span_dst_group:
+ <<: *add_ansible_group_2
+ state: absent
+ register: nm_remove_ansible_group_2
+
+- name: Remove access span destination group type access interface direct port channel
+ cisco.aci.aci_access_span_dst_group:
+ <<: *add_ansible_group_3
+ state: absent
+ register: nm_remove_ansible_group_3
+
+- name: Verify remove access span destination groups
+ 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 == []
+ - nm_remove_ansible_group_2 is changed
+ - nm_remove_ansible_group_2.current == []
+ - nm_remove_ansible_group_2.previous | length == 1
+ - nm_remove_ansible_group_3 is changed
+ - nm_remove_ansible_group_3.current == []
+ - nm_remove_ansible_group_3.previous | length == 1
+
+# TEST INCORRECT MODULE INPUT
+
+- name: Mutually exclusive parameters provided together (error)
+ cisco.aci.aci_access_span_dst_group:
+ <<: *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
+ access_interface:
+ pod: 1
+ node: 101
+ path: test-PolGrp
+ state: present
+ register: incorrect_input_both_types
+ ignore_errors: true
+
+- name: Missing input parameters for state is present (error)
+ cisco.aci.aci_access_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_group_1
+ description: test span epg
+ register: incorrect_input_no_types
+ ignore_errors: true
+
+- name: Verify incorrect module input
+ ansible.builtin.assert:
+ that:
+ - incorrect_input_both_types.msg == "parameters are mutually exclusive{{':'}} access_interface|destination_epg"
+ - incorrect_input_no_types.msg == "state is present but any of the following are missing{{':'}} access_interface, destination_epg" \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_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_filter_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/tasks/main.yml
new file mode 100644
index 000000000..c071f747a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group/tasks/main.yml
@@ -0,0 +1,154 @@
+# 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") }}'
+
+- 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 == []
+ block:
+
+ # CLEAN TEST ENVIRONMENT
+
+ - name: Query all access span filter groups
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+ - name: Clean access span filter groups
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item.spanFilterGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+ # TEST CREATE FILTER GROUPS
+
+ - name: Add access span filter group ( check mode )
+ cisco.aci.aci_access_span_filter_group: &add_ansible_filter_group_1
+ <<: *aci_info
+ filter_group: ansible_group_1
+ state: present
+ check_mode: true
+ register: cm_add_ansible_group_1
+
+ - name: Add access span filter group
+ cisco.aci.aci_access_span_filter_group:
+ <<: *add_ansible_filter_group_1
+ register: nm_add_ansible_group_1
+
+ - name: Add access span filter group again
+ cisco.aci.aci_access_span_filter_group:
+ <<: *add_ansible_filter_group_1
+ register: nm_add_ansible_group_1_again
+
+ - name: Verify add access span filter group
+ 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.spanFilterGrp.attributes.name == "ansible_group_1"
+ - nm_add_ansible_group_1 is changed
+ - nm_add_ansible_group_1.previous == []
+ - nm_add_ansible_group_1.current.0.spanFilterGrp.attributes.name == "ansible_group_1"
+ - nm_add_ansible_group_1_again is not changed
+ - nm_add_ansible_group_1_again.previous.0.spanFilterGrp.attributes.name == "ansible_group_1"
+ - nm_add_ansible_group_1_again.current.0.spanFilterGrp.attributes.name == "ansible_group_1"
+
+ - name: Add two more access span filter groups
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item }}"
+ state: present
+ loop:
+ - ansible_group_2
+ - ansible_group_3
+
+ # TEST QUERY FILTER GROUPS
+
+ - name: Query access span filter group
+ cisco.aci.aci_access_span_filter_group:
+ <<: *add_ansible_filter_group_1
+ state: query
+ register: query_one
+
+ - name: Query all access span filter group ( class query )
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify access span filter group queries
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanFilterGrp.attributes.name == "ansible_group_1"
+ - query_all is not changed
+ - query_all.current | length == 3
+ - query_all.current.0.spanFilterGrp.attributes.name == "ansible_group_1"
+ - query_all.current.1.spanFilterGrp.attributes.name == "ansible_group_2"
+ - query_all.current.2.spanFilterGrp.attributes.name == "ansible_group_3"
+
+ # TEST REMOVAL FILTER GROUPS
+
+ - name: Remove access span filter group ( check mode )
+ cisco.aci.aci_access_span_filter_group: &remove_ansible_filter_group_1
+ <<: *add_ansible_filter_group_1
+ state: absent
+ check_mode: true
+ register: cm_remove_ansible_filter_group_1
+
+ - name: Remove access span filter group
+ cisco.aci.aci_access_span_filter_group:
+ <<: *remove_ansible_filter_group_1
+ register: nm_remove_ansible_filter_group_1
+
+ - name: Remove access span filter group again
+ cisco.aci.aci_access_span_filter_group:
+ <<: *remove_ansible_filter_group_1
+ register: nm_remove_ansible_filter_group_1_again
+
+ - name: Verify access span filter group removal
+ ansible.builtin.assert:
+ that:
+ - cm_remove_ansible_filter_group_1 is changed
+ - cm_remove_ansible_filter_group_1.proposed == {}
+ - nm_remove_ansible_filter_group_1 is changed
+ - nm_remove_ansible_filter_group_1.previous.0.spanFilterGrp.attributes.name == "ansible_group_1"
+ - nm_remove_ansible_filter_group_1.current == []
+ - nm_remove_ansible_filter_group_1_again is not changed
+ - nm_remove_ansible_filter_group_1_again.previous == []
+ - nm_remove_ansible_filter_group_1_again.current == []
+
+ # CLEAN TEST ENVIRONMENT
+
+ - name: Clean created access span filter groups
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item }}"
+ state: absent
+ loop:
+ - ansible_group_2
+ - ansible_group_3 \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/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_filter_group_entry/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml
new file mode 100644
index 000000000..788658f13
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_span_filter_group_entry/tasks/main.yml
@@ -0,0 +1,274 @@
+# 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") }}'
+
+- 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 == []
+ block:
+
+ # CLEAN TEST ENVIRONMENT
+
+ - name: Query all access span filter groups
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ state: query
+ register: query_for_clean
+
+ - name: Clean access span filter groups
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item.spanFilterGrp.attributes.name }}"
+ state: absent
+ loop: "{{ query_for_clean.current }}"
+
+ - name: Add access span filter group 1
+ cisco.aci.aci_access_span_filter_group: &add_ansible_filter_group_1
+ <<: *aci_info
+ filter_group: ansible_group_1
+ state: present
+
+ - name: Add access span filter group 2
+ cisco.aci.aci_access_span_filter_group: &add_ansible_filter_group_2
+ <<: *aci_info
+ filter_group: ansible_group_2
+ state: present
+
+ # TEST CREATE FILTER GROUP ENTRIES
+
+ - name: Add access span filter group entry 1 to ansible_group_1 ( checkmode )
+ cisco.aci.aci_access_span_filter_group_entry: &add_ansible_filter_group_entry_1
+ <<: *add_ansible_filter_group_1
+ source_ip: 1.1.1.1
+ destination_ip: 2.2.2.2
+ first_src_port: http
+ last_src_port: https
+ check_mode: true
+ register: cm_add_ansible_filter_group_entry_1
+
+ - name: Add access span filter group entry 1 to ansible_group_1
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *add_ansible_filter_group_entry_1
+ register: nm_add_ansible_filter_group_entry_1
+
+ - name: Add access span filter group entry 1 to ansible_group_1 again
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *add_ansible_filter_group_entry_1
+ register: nm_add_ansible_filter_group_entry_1_again
+
+ - name: Add access span filter group entry 2 to ansible_group_1 with ports as digits
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *add_ansible_filter_group_1
+ source_ip: 1.1.1.1
+ destination_ip: 3.3.3.3
+ first_src_port: http
+ last_src_port: https
+ first_dest_port: 80
+ last_dest_port: 443
+ ip_protocol: tcp
+ register: nm_add_ansible_filter_group_entry_2
+
+ - name: Add access span filter group entry 3 to ansible_group_1
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *add_ansible_filter_group_1
+ source_ip: 2.2.2.2
+ destination_ip: 5.5.5.5
+ register: nm_add_ansible_filter_group_entry_3
+
+ - name: Add access span filter group entry 4 to ansible_group_2
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *add_ansible_filter_group_2
+ source_ip: 2.2.2.2
+ destination_ip: 5.5.5.5
+ register: nm_add_ansible_filter_group_entry_4
+
+ - name: Verify add access span filter group entires
+ ansible.builtin.assert:
+ that:
+ - cm_add_ansible_filter_group_entry_1 is changed
+ - cm_add_ansible_filter_group_entry_1.previous == []
+ - cm_add_ansible_filter_group_entry_1.current == []
+ - cm_add_ansible_filter_group_entry_1.proposed.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - cm_add_ansible_filter_group_entry_1.proposed.spanFilterEntry.attributes.dstAddr == "2.2.2.2"
+ - cm_add_ansible_filter_group_entry_1.proposed.spanFilterEntry.attributes.srcAddr == "1.1.1.1"
+ - cm_add_ansible_filter_group_entry_1.proposed.spanFilterEntry.attributes.srcPortFrom == "http"
+ - cm_add_ansible_filter_group_entry_1.proposed.spanFilterEntry.attributes.srcPortTo == "https"
+ - nm_add_ansible_filter_group_entry_1 is changed
+ - nm_add_ansible_filter_group_entry_1.previous == []
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.dstAddr == "2.2.2.2"
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.srcAddr == "1.1.1.1"
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.srcPortFrom == "http"
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.srcPortTo == "https"
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.dstPortFrom == "unspecified"
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.dstPortTo == "unspecified"
+ - nm_add_ansible_filter_group_entry_1.current.0.spanFilterEntry.attributes.ipProto == "unspecified"
+ - nm_add_ansible_filter_group_entry_1_again is not changed
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.dstAddr == "2.2.2.2"
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.srcAddr == "1.1.1.1"
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.srcPortFrom == "http"
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.srcPortTo == "https"
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.dstPortFrom == "unspecified"
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.dstPortTo == "unspecified"
+ - nm_add_ansible_filter_group_entry_1_again.previous.0.spanFilterEntry.attributes.ipProto == "unspecified"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.dstAddr == "2.2.2.2"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.srcAddr == "1.1.1.1"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.srcPortFrom == "http"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.srcPortTo == "https"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.dstPortFrom == "unspecified"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.dstPortTo == "unspecified"
+ - nm_add_ansible_filter_group_entry_1_again.current.0.spanFilterEntry.attributes.ipProto == "unspecified"
+ - nm_add_ansible_filter_group_entry_2 is changed
+ - nm_add_ansible_filter_group_entry_2.previous == []
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-tcp-src-[1.1.1.1]-dst-[3.3.3.3]-srcPortFrom-http-srcPortTo-https-dstPortFrom-http-dstPortTo-https"
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.dstAddr == "3.3.3.3"
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.srcAddr == "1.1.1.1"
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.srcPortFrom == "http"
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.srcPortTo == "https"
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.dstPortFrom == "http"
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.dstPortTo == "https"
+ - nm_add_ansible_filter_group_entry_2.current.0.spanFilterEntry.attributes.ipProto == "tcp"
+ - nm_add_ansible_filter_group_entry_3 is changed
+ - nm_add_ansible_filter_group_entry_3.previous == []
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[2.2.2.2]-dst-[5.5.5.5]-srcPortFrom-unspecified-srcPortTo-unspecified-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.dstAddr == "5.5.5.5"
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.srcAddr == "2.2.2.2"
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.srcPortFrom == "unspecified"
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.srcPortTo == "unspecified"
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.dstPortFrom == "unspecified"
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.dstPortTo == "unspecified"
+ - nm_add_ansible_filter_group_entry_3.current.0.spanFilterEntry.attributes.ipProto == "unspecified"
+ - nm_add_ansible_filter_group_entry_4 is changed
+ - nm_add_ansible_filter_group_entry_4.previous == []
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_2/proto-unspecified-src-[2.2.2.2]-dst-[5.5.5.5]-srcPortFrom-unspecified-srcPortTo-unspecified-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.dstAddr == "5.5.5.5"
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.srcAddr == "2.2.2.2"
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.srcPortFrom == "unspecified"
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.srcPortTo == "unspecified"
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.dstPortFrom == "unspecified"
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.dstPortTo == "unspecified"
+ - nm_add_ansible_filter_group_entry_4.current.0.spanFilterEntry.attributes.ipProto == "unspecified"
+
+ # TEST QUERY FILTER GROUP ENTRIES
+
+ - name: Query one specific access span filter group entry
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *aci_info
+ source_ip: 1.1.1.1
+ destination_ip: 2.2.2.2
+ first_src_port: http
+ last_src_port: https
+ state: query
+ register: query_one
+
+ - name: Query all access span filter group entries of one entire group
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *add_ansible_filter_group_1
+ state: query
+ register: query_one_group
+
+ - name: Query all access span filter group entries ( class query )
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Query access span filter group entries that match source_ip and first_dest_port
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *aci_info
+ source_ip: 1.1.1.1
+ first_src_port: http
+ state: query
+ register: query_match
+
+ - name: Query access span filter group entries that match source_ip and first_dest_port with ports as digits
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *aci_info
+ source_ip: 1.1.1.1
+ first_src_port: 80
+ last_src_port: 443
+ state: query
+ register: query_match_port_number
+
+ - name: Verify access span filter group queries
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current | length == 1
+ - query_one.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - query_one_group is not changed
+ - query_one_group.current.0.spanFilterGrp.children | length == 3
+ - query_all is not changed
+ - query_all.current | length == 4
+ - query_match is not changed
+ - query_match.current | length == 2
+ - query_match.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - query_match.current.1.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-tcp-src-[1.1.1.1]-dst-[3.3.3.3]-srcPortFrom-http-srcPortTo-https-dstPortFrom-http-dstPortTo-https"
+ - query_match_port_number is not changed
+ - query_match_port_number.current | length == 2
+ - query_match_port_number.current.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - query_match_port_number.current.1.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-tcp-src-[1.1.1.1]-dst-[3.3.3.3]-srcPortFrom-http-srcPortTo-https-dstPortFrom-http-dstPortTo-https"
+
+ # TEST REMOVAL FILTER GROUP ENTRIES
+
+ - name: Remove access span filter group ( checkmode )
+ cisco.aci.aci_access_span_filter_group_entry: &remove_ansible_filter_group_entry_1
+ <<: *add_ansible_filter_group_entry_1
+ state: absent
+ check_mode: true
+ register: cm_remove_ansible_filter_group_1_entry
+
+ - name: Remove access span filter group
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *remove_ansible_filter_group_entry_1
+ register: nm_remove_ansible_filter_group_1_entry
+
+ - name: Remove access span filter group again
+ cisco.aci.aci_access_span_filter_group_entry:
+ <<: *remove_ansible_filter_group_entry_1
+ register: nm_remove_ansible_filter_group_1_entry_again
+
+ - name: Verify access span filter group entries removal
+ ansible.builtin.assert:
+ that:
+ - cm_remove_ansible_filter_group_1_entry is changed
+ - cm_remove_ansible_filter_group_1_entry.proposed == {}
+ - nm_remove_ansible_filter_group_1_entry is changed
+ - nm_remove_ansible_filter_group_1_entry.current == []
+ - nm_remove_ansible_filter_group_1_entry.previous.0.spanFilterEntry.attributes.dn == "uni/infra/filtergrp-ansible_group_1/proto-unspecified-src-[1.1.1.1]-dst-[2.2.2.2]-srcPortFrom-http-srcPortTo-https-dstPortFrom-unspecified-dstPortTo-unspecified"
+ - nm_remove_ansible_filter_group_1_entry_again is not changed
+ - nm_remove_ansible_filter_group_1_entry_again.current == []
+ - nm_remove_ansible_filter_group_1_entry_again.previous == []
+
+ # CLEAN TEST ENVIRONMENT
+
+ - name: Clean created access span filter groups
+ cisco.aci.aci_access_span_filter_group:
+ <<: *aci_info
+ filter_group: "{{ item }}"
+ state: absent
+ loop:
+ - ansible_group_1
+ - ansible_group_2
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/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_sub_port_block_to_access_port/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml
new file mode 100644
index 000000000..b986f5762
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml
@@ -0,0 +1,148 @@
+# Test code for the ACI modules
+# 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)
+
+- 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
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensuring Interface Policy Leaf profile exists for kick off
+ cisco.aci.aci_interface_policy_leaf_profile: &aci_interface_policy_leaf_profile_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
+ leaf_interface_profile: leafintprftest
+ register: leaf_profile_present
+
+ - name: Ensure Interface Access Port Selector exists for kick of
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile: &aci_access_port_to_interface_policy_leaf_profile_present
+ <<: *aci_interface_policy_leaf_profile_present
+ access_port_selector: anstest_accessportselector
+
+ # TODO: Ensure that leaf Policy Group Exists (module missing) (infra:AccPortGrp)
+
+ - name: Bind an Access Sub Port Block to an Interface Access Port Selector - check mode works
+ cisco.aci.aci_access_sub_port_block_to_access_port: &aci_access_sub_port_block_to_access_port_present
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ leaf_port_blk: anstest_leafportblkname
+ leaf_port_blk_description: anstest_leafportblkdesc
+ fromPort: 13
+ toPort: 13
+ fromSubPort: 1
+ toSubPort: 3
+ check_mode: true
+ register: accesssubportblock_to_accessport_check_mode_present
+
+ - name: Bind an Access Sub Port Block to an Interface Access Port Selector - creation works
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_sub_port_block_to_access_port_present
+ register: accesssubportblock_to_accessport_present
+
+ - name: Bind an Access Sub Port Block to an Interface Access Port Selector - idempotency works
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_sub_port_block_to_access_port_present
+ register: accesssubportblock_to_accessport_idempotent
+
+ - name: Bind an Access Sub Port Block to an Interface Access Port Selector - update works
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_sub_port_block_to_access_port_present
+ toSubPort: 2
+ register: accesssubportblock_to_accessport_update
+
+ # TODO: also test for errors
+ - name: present assertions
+ assert:
+ that:
+ - accesssubportblock_to_accessport_check_mode_present is changed
+ - accesssubportblock_to_accessport_present is changed
+ - accesssubportblock_to_accessport_present.current.0.infraSubPortBlk.attributes.annotation == 'orchestrator:ansible'
+ - accesssubportblock_to_accessport_present.previous == []
+ - accesssubportblock_to_accessport_present.sent.infraSubPortBlk.attributes.descr == 'anstest_leafportblkdesc'
+ - accesssubportblock_to_accessport_present.sent.infraSubPortBlk.attributes.name == 'anstest_leafportblkname'
+ - accesssubportblock_to_accessport_present.sent.infraSubPortBlk.attributes.fromPort == accesssubportblock_to_accessport_present.sent.infraSubPortBlk.attributes.toPort == '13'
+ - accesssubportblock_to_accessport_present.sent.infraSubPortBlk.attributes.fromSubPort == '1'
+ - accesssubportblock_to_accessport_present.sent.infraSubPortBlk.attributes.toSubPort == '3'
+ - accesssubportblock_to_accessport_idempotent is not changed
+ - accesssubportblock_to_accessport_idempotent.sent == {}
+ - accesssubportblock_to_accessport_update is changed
+ - accesssubportblock_to_accessport_update.sent.infraSubPortBlk.attributes.toSubPort == '2'
+
+
+ - name: Query Specific sub port block and access_port_selector binding
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_sub_port_block_to_access_port_present
+ state: query
+ register: binding_query
+
+ - name: present assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query.current | length >= 1
+ - '"api/mo/uni/infra/accportprof-leafintprftest/hports-anstest_accessportselector-typ-range/subportblk-anstest_leafportblkname.json" in binding_query.url'
+
+ - name: Remove binding of Access Sub Port Block and Interface Access Port Selector - check mode
+ cisco.aci.aci_access_sub_port_block_to_access_port: &aci_access_sub_port_block_to_access_port_absent
+ <<: *aci_access_sub_port_block_to_access_port_present
+ state: absent
+ check_mode: true
+ register: accesssubportblock_to_accessport_check_mode_absent
+
+ - name: Remove binding of Access Sub Port Block and Interface Access Port Selector - delete works
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_sub_port_block_to_access_port_absent
+ register: accesssubportblock_to_accessport_absent
+
+ - name: Remove binding of Access Sub Port Block and Interface Access Port Selector - idempotency works
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_sub_port_block_to_access_port_absent
+ register: accesssubportblock_to_accessport_absent_idempotent
+
+ - name: Remove binding of Access Sub Port Block and Interface Access Port Selector - check mode
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ #leaf_port_blk: anstest_leafportblkname
+ state: absent
+ ignore_errors: true
+ register: accesssubportblock_to_accessport_absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - accesssubportblock_to_accessport_check_mode_absent is changed
+ - accesssubportblock_to_accessport_check_mode_absent.previous != []
+ - accesssubportblock_to_accessport_absent is changed
+ - accesssubportblock_to_accessport_absent.previous == accesssubportblock_to_accessport_check_mode_absent.previous
+ - accesssubportblock_to_accessport_absent_idempotent is not changed
+ - accesssubportblock_to_accessport_absent_idempotent.previous == []
+ - accesssubportblock_to_accessport_absent_missing_param is failed
+ - 'accesssubportblock_to_accessport_absent_missing_param.msg == "state is absent but all of the following are missing: leaf_port_blk"'
+
+
+ - name: Remove binding of Access Sub Port Block and Interface Access Port Selector - Clean up
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ <<: *aci_access_sub_port_block_to_access_port_present
+ state: absent
+
+ - name: Remove Interface Access Port Selector - Cleanup
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ <<: *aci_access_port_to_interface_policy_leaf_profile_present
+ state: absent
+
+ - name: Remove Interface policy leaf profile - Cleanup
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml
new file mode 100644
index 000000000..1a389a9fc
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml
@@ -0,0 +1,338 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.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: 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: Remove AEP
+ cisco.aci.aci_aep: &aep_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") }}'
+ aep: '{{ item }}'
+ state: absent
+ loop:
+ - ansible_test
+ - ansible_test2
+ - ansible_test3
+
+ # ADD AEP
+ - name: Add AEP (check_mode)
+ cisco.aci.aci_aep: &aep_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") }}'
+ aep: ansible_test
+ infra_vlan: true
+ state: present
+ check_mode: true
+ register: cm_add_aep
+
+ - name: Add AEP (normal mode)
+ cisco.aci.aci_aep: *aep_present
+ register: nm_add_aep
+
+ - name: Add another AEP (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ aep: ansible_test2
+ infra_vlan: true
+ register: nm_add_aep2
+
+ - name: Add another AEP (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ aep: ansible_test3
+ infra_vlan: false
+ register: nm_add_aep3
+
+ - name: Verify add_aep
+ assert:
+ that:
+ - cm_add_aep is changed
+ - nm_add_aep is changed
+ - nm_add_aep.current.0.infraAttEntityP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_aep2 is changed
+ - nm_add_aep3 is changed
+ - nm_add_aep.previous == nm_add_aep.previous == cm_add_aep.current == []
+ - nm_add_aep.current[0].infraAttEntityP.attributes.dn == 'uni/infra/attentp-ansible_test'
+ - nm_add_aep.current[0].infraAttEntityP.attributes.name == 'ansible_test'
+ - cm_add_aep.proposed.infraAttEntityP.attributes.name == nm_add_aep.proposed.infraAttEntityP.attributes.name == cm_add_aep.sent.infraAttEntityP.attributes.name == nm_add_aep.sent.infraAttEntityP.attributes.name == 'ansible_test'
+ - nm_add_aep2.current[0].infraAttEntityP.children[0].infraProvAcc.attributes.name == 'provacc'
+ - nm_add_aep3.current[0].infraAttEntityP | length == 1
+
+ - name: Change AEP infra(normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ aep: ansible_test2
+ infra_vlan: false
+ register: nm_add_aep_true_to_false
+
+ - name: Change AEP infra again(normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ aep: ansible_test2
+ infra_vlan: false
+ register: nm_add_aep_true_to_false_again
+
+ - name: Add AEP again (check_mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ check_mode: true
+ register: cm_add_aep_again
+
+ - name: Add AEP again (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ register: nm_add_aep_again
+
+ - name: Verify add_aep_again
+ assert:
+ that:
+ - cm_add_aep_again is not changed
+ - nm_add_aep_again is not changed
+ - nm_add_aep_again.previous[0].infraAttEntityP.attributes.dn == nm_add_aep_again.previous[0].infraAttEntityP.attributes.dn == cm_add_aep_again.current[0].infraAttEntityP.attributes.dn == nm_add_aep_again.current[0].infraAttEntityP.attributes.dn == 'uni/infra/attentp-ansible_test'
+ - nm_add_aep_again.previous[0].infraAttEntityP.attributes.name == nm_add_aep_again.previous[0].infraAttEntityP.attributes.name == cm_add_aep_again.current[0].infraAttEntityP.attributes.name == nm_add_aep_again.current[0].infraAttEntityP.attributes.name == 'ansible_test'
+ - cm_add_aep_again.proposed.infraAttEntityP.attributes.name == nm_add_aep_again.proposed.infraAttEntityP.attributes.name == 'ansible_test'
+ - cm_add_aep_again.sent == nm_add_aep_again.sent == {}
+ - nm_add_aep_true_to_false.current[0].infraAttEntityP | length == 1
+ - nm_add_aep_true_to_false_again.current[0].infraAttEntityP | length == 1
+
+ # CHANGE AEP
+ - name: Change description of AEP (check_mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ description: Ansible test AEP
+ check_mode: true
+ register: cm_add_aep_descr
+
+ - name: Change description of AEP (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ description: Ansible test AEP
+ register: nm_add_aep_descr
+
+ - name: Verify add_aep_descr
+ assert:
+ that:
+ - cm_add_aep_descr is changed
+ - nm_add_aep_descr is changed
+ - cm_add_aep_descr.proposed.infraAttEntityP.attributes.descr == nm_add_aep_descr.proposed.infraAttEntityP.attributes.descr == 'Ansible test AEP'
+ - cm_add_aep_descr.proposed.infraAttEntityP.attributes.name == nm_add_aep_descr.proposed.infraAttEntityP.attributes.name == 'ansible_test'
+ - cm_add_aep_descr.sent.infraAttEntityP.attributes.descr == nm_add_aep_descr.sent.infraAttEntityP.attributes.descr == 'Ansible test AEP'
+ - cm_add_aep_descr.previous.0.infraAttEntityP.attributes.dn == nm_add_aep_descr.previous.0.infraAttEntityP.attributes.dn == cm_add_aep_descr.current.0.infraAttEntityP.attributes.dn == 'uni/infra/attentp-ansible_test'
+ - cm_add_aep_descr.previous.0.infraAttEntityP.attributes.name == nm_add_aep_descr.previous.0.infraAttEntityP.attributes.name == cm_add_aep_descr.current.0.infraAttEntityP.attributes.name == 'ansible_test'
+ - nm_add_aep_descr.current.0.infraAttEntityP.attributes.descr == 'Ansible test AEP'
+ - nm_add_aep_descr.current.0.infraAttEntityP.attributes.dn == 'uni/infra/attentp-ansible_test'
+ - nm_add_aep_descr.current.0.infraAttEntityP.attributes.name == 'ansible_test'
+
+ - name: Change description of AEP again (check_mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ description: Ansible test AEP
+ check_mode: true
+ register: cm_add_aep_descr_again
+
+ - name: Change description of AEP again (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_present
+ description: Ansible test AEP
+ register: nm_add_aep_descr_again
+
+ - name: Verify add_aep_descr_again
+ assert:
+ that:
+ - cm_add_aep_descr_again is not changed
+ - nm_add_aep_descr_again is not changed
+ - cm_add_aep_descr_again.proposed.infraAttEntityP.attributes.descr == nm_add_aep_descr_again.proposed.infraAttEntityP.attributes.descr == 'Ansible test AEP'
+ - cm_add_aep_descr_again.proposed.infraAttEntityP.attributes.name == nm_add_aep_descr_again.proposed.infraAttEntityP.attributes.name == 'ansible_test'
+ - cm_add_aep_descr_again.sent == nm_add_aep_descr_again.sent == {}
+ - cm_add_aep_descr_again.previous[0].infraAttEntityP.attributes.descr == nm_add_aep_descr_again.previous[0].infraAttEntityP.attributes.descr == cm_add_aep_descr_again.current[0].infraAttEntityP.attributes.descr == nm_add_aep_descr_again.current[0].infraAttEntityP.attributes.descr == 'Ansible test AEP'
+ - cm_add_aep_descr_again.previous[0].infraAttEntityP.attributes.dn == nm_add_aep_descr_again.previous[0].infraAttEntityP.attributes.dn == cm_add_aep_descr_again.current[0].infraAttEntityP.attributes.dn == nm_add_aep_descr_again.current[0].infraAttEntityP.attributes.dn == 'uni/infra/attentp-ansible_test'
+ - cm_add_aep_descr_again.previous[0].infraAttEntityP.attributes.name == nm_add_aep_descr_again.previous[0].infraAttEntityP.attributes.name == cm_add_aep_descr_again.current[0].infraAttEntityP.attributes.name == nm_add_aep_descr_again.current[0].infraAttEntityP.attributes.name == 'ansible_test'
+
+
+ # ADD AEP AGAIN
+ - name: Add AEP again with no description (check_mode)
+ cisco.aci.aci_aep: *aep_present
+ check_mode: true
+ register: cm_add_aep_again_no_descr
+
+ - name: Add AEP again with no description (normal mode)
+ cisco.aci.aci_aep: *aep_present
+ register: nm_add_aep_again_no_descr
+
+ - name: Verify add_aep_again_no_descr
+ assert:
+ that:
+ - cm_add_aep_again_no_descr is not changed
+ - nm_add_aep_again_no_descr is not changed
+ - cm_add_aep_again_no_descr.proposed.infraAttEntityP.attributes.name == nm_add_aep_again_no_descr.proposed.infraAttEntityP.attributes.name == 'ansible_test'
+ - cm_add_aep_again_no_descr.sent == nm_add_aep_again_no_descr.sent == {}
+ - cm_add_aep_again_no_descr.previous[0].infraAttEntityP.attributes.descr == nm_add_aep_again_no_descr.previous[0].infraAttEntityP.attributes.descr == cm_add_aep_again_no_descr.current[0].infraAttEntityP.attributes.descr == nm_add_aep_again_no_descr.current[0].infraAttEntityP.attributes.descr == 'Ansible test AEP'
+ - cm_add_aep_again_no_descr.previous[0].infraAttEntityP.attributes.dn == nm_add_aep_again_no_descr.previous[0].infraAttEntityP.attributes.dn == cm_add_aep_again_no_descr.current[0].infraAttEntityP.attributes.dn == nm_add_aep_again_no_descr.current[0].infraAttEntityP.attributes.dn == 'uni/infra/attentp-ansible_test'
+ - cm_add_aep_again_no_descr.previous[0].infraAttEntityP.attributes.name == nm_add_aep_again_no_descr.previous[0].infraAttEntityP.attributes.name == cm_add_aep_again_no_descr.current[0].infraAttEntityP.attributes.name == nm_add_aep_again_no_descr.current[0].infraAttEntityP.attributes.name == 'ansible_test'
+
+
+ # QUERY ALL AEPS
+ - name: Query all AEPs (check_mode)
+ cisco.aci.aci_aep: &aep_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_aeps
+
+ - name: Query all AEPs (normal mode)
+ cisco.aci.aci_aep: *aep_query
+ register: nm_query_all_aeps
+
+ - name: Verify query_all_aeps
+ assert:
+ that:
+ - cm_query_all_aeps is not changed
+ - nm_query_all_aeps is not changed
+ - cm_query_all_aeps == nm_query_all_aeps
+ - nm_query_all_aeps.current|length >= 1
+
+
+ # QUERY A AEP
+ - name: Query our AEP
+ cisco.aci.aci_aep:
+ <<: *aep_query
+ aep: ansible_test
+ check_mode: true
+ register: cm_query_aep
+
+ - name: Query our AEP
+ cisco.aci.aci_aep:
+ <<: *aep_query
+ aep: ansible_test
+ register: nm_query_aep
+
+ - name: Verify query_aep
+ assert:
+ that:
+ - cm_query_aep is not changed
+ - nm_query_aep is not changed
+ - cm_query_aep == nm_query_aep
+ - nm_query_aep.current.0.infraAttEntityP.attributes.descr == "Ansible test AEP"
+ - nm_query_aep.current.0.infraAttEntityP.attributes.dn == "uni/infra/attentp-ansible_test"
+ - nm_query_aep.current.0.infraAttEntityP.attributes.name == "ansible_test"
+
+
+ # REMOVE AEP
+ - name: Remove AEP (check_mode)
+ cisco.aci.aci_aep:
+ <<: *aep_absent
+ aep: ansible_test
+ check_mode: true
+ register: cm_remove_aep
+
+ - name: Remove AEP (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_absent
+ aep: ansible_test
+ register: nm_remove_aep
+
+ - name: Verify remove_aep
+ assert:
+ that:
+ - cm_remove_aep is changed
+ - nm_remove_aep is changed
+ - cm_remove_aep.proposed == nm_remove_aep.proposed == {}
+ - cm_remove_aep.sent == nm_remove_aep.sent == {}
+ - cm_remove_aep.previous[0].infraAttEntityP.attributes.name == nm_remove_aep.previous[0].infraAttEntityP.attributes.name == cm_remove_aep.current[0].infraAttEntityP.attributes.name == 'ansible_test'
+ - cm_remove_aep.previous[0].infraAttEntityP.attributes.descr == nm_remove_aep.previous[0].infraAttEntityP.attributes.descr == cm_remove_aep.current[0].infraAttEntityP.attributes.descr == 'Ansible test AEP'
+ - cm_remove_aep.previous[0].infraAttEntityP.attributes.dn == nm_remove_aep.previous[0].infraAttEntityP.attributes.dn == cm_remove_aep.current[0].infraAttEntityP.attributes.dn == 'uni/infra/attentp-ansible_test'
+ - nm_remove_aep.current == []
+
+ - name: Remove AEP again (check_mode)
+ cisco.aci.aci_aep:
+ <<: *aep_absent
+ aep: ansible_test
+ check_mode: true
+ register: cm_remove_aep_again
+
+ - name: Remove AEP again (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_absent
+ aep: ansible_test
+ register: nm_remove_aep_again
+
+ - name: Verify remove_aep_again
+ assert:
+ that:
+ - cm_remove_aep_again is not changed
+ - nm_remove_aep_again is not changed
+ - cm_remove_aep_again.proposed == nm_remove_aep_again.proposed == {}
+ - cm_remove_aep_again.sent == nm_remove_aep_again.sent == {}
+ - cm_remove_aep_again.previous == nm_remove_aep_again.previous == cm_remove_aep_again.current == nm_remove_aep_again.current == []
+
+
+ # QUERY NON-EXISTING AEP
+ - name: Query non-existing AEP (check_mode)
+ cisco.aci.aci_aep:
+ <<: *aep_query
+ aep: ansible_test
+ check_mode: true
+ register: cm_query_non_aep
+
+ - name: Query non-existing AEP (normal mode)
+ cisco.aci.aci_aep:
+ <<: *aep_query
+ aep: ansible_test
+ register: nm_query_non_aep
+
+ - name: Verify query_non_aep
+ assert:
+ that:
+ - cm_query_non_aep is not changed
+ - nm_query_non_aep is not changed
+ - cm_query_non_aep == nm_query_non_aep
+ - cm_query_non_aep.current == nm_query_non_aep.current == []
+
+
+ # PROVOKE ERRORS
+ - name: Error when required parameter is missing
+ 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") }}'
+ state: present
+ ignore_errors: true
+ register: error_on_missing_required_param
+
+ - name: Verify error_on_missing_required_param
+ assert:
+ that:
+ - error_on_missing_required_param is failed
+ - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: aep"'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..a69d255ff
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml
@@ -0,0 +1,223 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.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: 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: 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") }}'
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ 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") }}'
+ 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") }}'
+ domain: phys_dom
+ domain_type: phys
+ state: present
+
+
+ # 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") }}'
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ state: present
+ check_mode: true
+ register: cm_add_binding
+
+ - name: Add AEP to domain binding (normal mode)
+ cisco.aci.aci_aep_to_domain: *binding_present
+ register: nm_add_binding
+
+ - name: Verify add_binding
+ assert:
+ that:
+ - cm_add_binding is changed
+ - nm_add_binding is changed
+ - nm_add_binding.current.0.infraRsDomP.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_binding.sent.infraRsDomP.attributes.tDn == nm_add_binding.sent.infraRsDomP.attributes.tDn == 'uni/phys-phys_dom'
+ - cm_add_binding.proposed.infraRsDomP.attributes.tDn == nm_add_binding.proposed.infraRsDomP.attributes.tDn == 'uni/phys-phys_dom'
+ - cm_add_binding.current == cm_add_binding.previous == nm_add_binding.previous == []
+ - nm_add_binding.current[0].infraRsDomP.attributes.dn == 'uni/infra/attentp-test_aep/rsdomP-[uni/phys-phys_dom]'
+ - nm_add_binding.current[0].infraRsDomP.attributes.tDn == 'uni/phys-phys_dom'
+
+ - name: Add AEP to domain binding again (check_mode)
+ cisco.aci.aci_aep_to_domain: *binding_present
+ check_mode: true
+ register: cm_add_binding_again
+
+ - name: Add AEP to domain binding again (normal mode)
+ cisco.aci.aci_aep_to_domain: *binding_present
+ register: nm_add_binding_again
+
+ - name: Verify add_binding_again
+ assert:
+ that:
+ - cm_add_binding_again is not changed
+ - nm_add_binding_again is not changed
+
+
+ # 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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_bindings
+
+ - name: Query all AEP to domain bindings (normal mode)
+ cisco.aci.aci_aep_to_domain: *binding_query
+ register: nm_query_all_bindings
+
+ - name: Verify query_all_bindings
+ assert:
+ that:
+ - cm_query_all_bindings is not changed
+ - nm_query_all_bindings is not changed
+ - cm_query_all_bindings == nm_query_all_bindings
+ - nm_query_all_bindings.current|length >= 1
+
+
+ # QUERY A BINDING
+ - name: Query our AEP to domain binding (check_mode)
+ cisco.aci.aci_aep_to_domain:
+ <<: *binding_query
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ check_mode: true
+ register: cm_query_binding
+
+ - name: Query our AEP to domain binding (normal mode)
+ cisco.aci.aci_aep_to_domain:
+ <<: *binding_query
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ register: nm_query_binding
+
+ - name: Verify query_binding
+ assert:
+ that:
+ - cm_query_binding is not changed
+ - nm_query_binding is not changed
+ - cm_query_binding == nm_query_binding
+ - nm_query_binding.current.0.infraRsDomP.attributes.dn == 'uni/infra/attentp-test_aep/rsdomP-[uni/phys-phys_dom]'
+ - nm_query_binding.current.0.infraRsDomP.attributes.tCl == 'physDomP'
+ - nm_query_binding.current.0.infraRsDomP.attributes.tDn == 'uni/phys-phys_dom'
+
+
+ # REMOVE BINDING
+ - name: Remove AEP to domain binding (check_mode)
+ cisco.aci.aci_aep_to_domain: *binding_absent
+ check_mode: true
+ register: cm_remove_binding
+
+ - name: Remove AEP to domain binding (normal mode)
+ cisco.aci.aci_aep_to_domain: *binding_absent
+ register: nm_remove_binding
+
+ - name: Verify remove_binding
+ assert:
+ that:
+ - cm_remove_binding is changed
+ - nm_remove_binding is changed
+ - cm_remove_binding.current.0.infraRsDomP.attributes.dn == cm_remove_binding.previous.0.infraRsDomP.attributes.dn == nm_remove_binding.previous.0.infraRsDomP.attributes.dn == 'uni/infra/attentp-test_aep/rsdomP-[uni/phys-phys_dom]'
+ - cm_remove_binding.current.0.infraRsDomP.attributes.tDn == cm_remove_binding.previous.0.infraRsDomP.attributes.tDn == nm_remove_binding.previous.0.infraRsDomP.attributes.tDn == 'uni/phys-phys_dom'
+ - nm_remove_binding.current == []
+
+ - name: Remove AEP to domain binding again (check_mode)
+ cisco.aci.aci_aep_to_domain: *binding_absent
+ check_mode: true
+ register: cm_remove_binding_again
+
+ - name: Remove AEP to domain binding again (normal mode)
+ cisco.aci.aci_aep_to_domain: *binding_absent
+ register: nm_remove_binding_again
+
+ - name: Verify remove_binding_again
+ assert:
+ that:
+ - cm_remove_binding_again is not changed
+ - nm_remove_binding_again is not changed
+
+
+ # QUERY NON-EXISTING BINDING
+ - name: Query non-existing AEP to domain binding (check_mode)
+ cisco.aci.aci_aep_to_domain:
+ <<: *binding_query
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ check_mode: true
+ register: cm_query_non_binding
+
+ - name: Query non-existing AEP to domain binding (normal mode)
+ cisco.aci.aci_aep_to_domain:
+ <<: *binding_query
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ register: nm_query_non_binding
+
+ - name: Verify query_non_binding
+ assert:
+ that:
+ - cm_query_non_binding is not changed
+ - nm_query_non_binding is not changed
+ - cm_query_non_binding == nm_query_non_binding
+ - nm_query_non_binding.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml
new file mode 100644
index 000000000..86ee212bd
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_epg/tasks/main.yml
@@ -0,0 +1,235 @@
+# Test code for the aep_to_epg ACI module
+# Author: Marcel Zehnder (@maercu)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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 execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ # CLEAN ENVIRONMENT
+ - name: Remove test aep before we kickoff
+ cisco.aci.aci_aep: &aep_absent
+ <<: *aci_info
+ aep: epg2aep
+ state: absent
+
+ # SETUP TEST AEP AND EPGS
+ - name: Create AEP
+ cisco.aci.aci_aep: &aep_present
+ <<: *aci_info
+ aep: epg2aep
+ state: present
+
+ - name: Create Tenant
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+
+ - name: Configure VRF
+ cisco.aci.aci_vrf:
+ <<: *tenant_present
+ vrf: epg2aep
+
+ - name: Configure BD
+ cisco.aci.aci_bd:
+ <<: *tenant_present
+ vrf: epg2aep
+ bd: epg2aep
+
+ - name: Configure Ap
+ cisco.aci.aci_ap:
+ <<: *tenant_present
+ ap: ap
+
+ - name: Configure EPG
+ cisco.aci.aci_epg:
+ <<: *tenant_present
+ ap: ap
+ epg: '{{ item }}'
+ bd: epg2aep
+ loop:
+ - epg1
+ - epg2
+
+ # ADD ASSOCIATION
+ - name: Add EPG to AEP association (check_mode)
+ cisco.aci.aci_aep_to_epg: &assoc_present
+ <<: *aep_present
+ tenant: ansible_test
+ ap: ap
+ epg: epg1
+ encap: 1984
+ interface_mode: trunk
+ check_mode: true
+ register: cm_add_assoc
+
+ - name: Add EPG to AEP association (normal mode)
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_present
+ register: nm_add_assoc
+
+ - name: Verify add_assoc
+ assert:
+ that:
+ - cm_add_assoc is changed
+ - nm_add_assoc is changed
+ - nm_add_assoc.current.0.infraGeneric.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_assoc.previous == nm_add_assoc.previous == []
+ - cm_add_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.encap == nm_add_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.encap == 'vlan-1984'
+ - cm_add_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.mode == nm_add_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.mode == 'regular'
+ - cm_add_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.tDn == nm_add_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.tDn == 'uni/tn-ansible_test/ap-ap/epg-epg1'
+
+ - name: Add EPG to AEP association again, check if idempotency works (check_mode)
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_present
+ check_mode: true
+ register: cm_add_assoc_again
+
+ - name: Add EPG to AEP association again, check if idempotency works (normal_mode)
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_present
+ register: nm_add_assoc_again
+
+ - name: Verify add_assoc_again
+ assert:
+ that:
+ - cm_add_assoc_again is not changed
+ - nm_add_assoc_again is not changed
+
+ # UPDATE ASSOCIATION
+ - name: Change encap (check_mode)
+ cisco.aci.aci_aep_to_epg: &assoc_update
+ <<: *assoc_present
+ encap: 1985
+ primary_encap: 1986
+ check_mode: true
+ register: cm_update_assoc
+
+ - name: Change encap (normal_mode)
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_update
+ register: nm_update_assoc
+
+ - name: Verify update_assoc
+ assert:
+ that:
+ - cm_update_assoc is changed
+ - nm_update_assoc is changed
+ - cm_update_assoc.previous == nm_update_assoc.previous != []
+ - cm_update_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.encap == nm_update_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.encap == 'vlan-1985'
+ - cm_update_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.primaryEncap == nm_update_assoc.sent.infraGeneric.children[0].infraRsFuncToEpg.attributes.primaryEncap == 'vlan-1986'
+
+ # ADD ANOTHER ASSOCIATION
+ - name: Add another EPG to AEP association
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_present
+ epg: epg2
+ encap: 1990
+
+ # QUERY ALL ASSOCIATIONS
+ - name: Query all EPG to AEP association
+ cisco.aci.aci_aep_to_epg:
+ <<: *aci_info
+ state: query
+ register: query_all_assocs
+
+ - name: Verify query_all_assocs
+ assert:
+ that:
+ - query_all_assocs is not changed
+ - query_all_assocs.current|length >= 1
+
+ # QUERY A SPECIFIC ASSOCIATION
+ - name: Query a specific EPG to AEP association
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_update
+ state: query
+ register: query_spec_assoc
+
+ - name: Verify query_spec_assoc
+ assert:
+ that:
+ - query_spec_assoc is not changed
+ - query_spec_assoc.current|length == 1
+
+ # REMOVE A SPECIFIC ASSOCIATION
+ - name: Remove EPG1 to AEP association (check_mode)
+ cisco.aci.aci_aep_to_epg: &assoc_remove
+ <<: *assoc_update
+ state: absent
+ check_mode: true
+ register: cm_remove_spec_assoc
+
+ - name: Remove EPG1 to AEP association (normal mode)
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_remove
+ register: nm_remove_spec_assoc
+
+ - name: Verify remove_spec_assoc
+ assert:
+ that:
+ - cm_remove_spec_assoc is changed
+ - nm_remove_spec_assoc is changed
+ - nm_remove_spec_assoc.current == []
+
+ - name: Remove EPG1 to AEP association again (normal mode)
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_remove
+ register: nm_remove_spec_assoc_again
+
+ - name: Verify remove_spec_assoc_again
+ assert:
+ that:
+ - nm_remove_spec_assoc_again is not changed
+
+ # QUERY A STILL EXISTING ASSOCIATION
+ - name: Query EPG2 to AEP association
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_present
+ epg: epg2
+ state: query
+ register: query_existing_assoc
+
+ - name: Verify query_existing_assoc
+ assert:
+ that:
+ - query_existing_assoc is not changed
+ - query_existing_assoc.current|length == 1
+
+ # QUERY NON-EXISTING ASSOCIATION
+ - name: Query non-existing EPG to AEP association (normal mode)
+ cisco.aci.aci_aep_to_epg:
+ <<: *assoc_update
+ state: query
+ register: nm_query_non_exist
+
+ - name: Verify nm_query_non_exist
+ assert:
+ that:
+ - nm_query_non_exist is not changed
+ - nm_query_non_exist.current == []
+
+ # CLEANUP
+ - name: Cleanup AEP
+ cisco.aci.aci_aep:
+ <<: *aep_absent
+
+ - name: Delete Tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml
new file mode 100644
index 000000000..c527a9059
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml
@@ -0,0 +1,202 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: ensure tenant does not exists
+ cisco.aci.aci_tenant: &aci_tenant_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
+ 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
+ register: tenant_present
+
+ - name: ensure monitoring policy exists
+ cisco.aci.aci_epg_monitoring_policy:
+ 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
+ monitoring_policy: check
+ tenant: ansible_test
+
+ - name: ensure ap does not exist initially
+ cisco.aci.aci_ap:
+ <<: *aci_tenant_present
+ ap: anstest
+ state: absent
+
+ - name: create ap - check mode works
+ cisco.aci.aci_ap: &aci_ap_present
+ <<: *aci_tenant_present
+ ap: anstest
+ description: Ansible Test
+ monitoring_policy: check
+ check_mode: true
+ register: ap_present_check_mode
+
+ - name: create ap - creation works
+ cisco.aci.aci_ap:
+ <<: *aci_ap_present
+ register: ap_present
+
+ - name: create ap - extra for query
+ cisco.aci.aci_ap:
+ <<: *aci_tenant_present
+ ap: anstest2
+
+ - name: create ap - idempotency works
+ cisco.aci.aci_ap:
+ <<: *aci_ap_present
+ register: ap_present_idempotent
+
+ - name: update ap - update works
+ cisco.aci.aci_ap:
+ <<: *aci_ap_present
+ description: Ansible Test Update
+ register: ap_present_update
+
+ - name: create ap - creation works
+ cisco.aci.aci_ap:
+ <<: *aci_tenant_present
+ ignore_errors: true
+ register: ap_present_missing_param
+
+ - name: present asserts
+ assert:
+ that:
+ - ap_present_check_mode is changed
+ - ap_present is changed
+ - ap_present.previous == []
+ - ap_present.current.0.fvAp.children.0.fvRsApMonPol.attributes.tnMonEPGPolName == 'check'
+ - ap_present.current.0.fvAp.attributes.annotation == 'orchestrator:ansible'
+ - ap_present.sent == ap_present_check_mode.sent
+ - ap_present.sent.fvAp.attributes.descr == 'Ansible Test'
+ - ap_present.sent.fvAp.attributes.name == 'anstest'
+ - ap_present_idempotent is not changed
+ - ap_present_idempotent.previous != []
+ - ap_present_idempotent.sent == {}
+ - ap_present_update is changed
+ - ap_present_update.sent.fvAp.attributes.descr == 'Ansible Test Update'
+ - ap_present_missing_param is failed
+ - 'ap_present_missing_param.msg == "state is present but all of the following are missing: ap"'
+
+ - name: get ap - query specific ap
+ cisco.aci.aci_ap: &aci_ap_query
+ <<: *aci_ap_present
+ state: query
+ register: query_ap
+
+ - name: get all ap for tenant - query tenant aps
+ cisco.aci.aci_ap:
+ <<: *aci_ap_query
+ ap: "{{ fakevar | default(omit) }}"
+ register: query_ap_tenant
+
+ - name: get all ap by name - query ap name
+ cisco.aci.aci_ap:
+ <<: *aci_ap_query
+ tenant: "{{ fakevar | default(omit) }}"
+ register: query_ap_ap
+
+ - name: get all aps - query general
+ cisco.aci.aci_ap:
+ <<: *aci_ap_query
+ tenant: "{{ fakevar | default(omit) }}"
+ ap: "{{ fakevar | default(omit) }}"
+ register: query_all
+
+ - name: query assertions
+ assert:
+ that:
+ - query_ap is not changed
+ - query_ap.current | length == 1
+ - query_ap.current.0.fvAp.attributes.name == "anstest"
+ - query_ap.current.0.fvAp.children.0.fvRsApMonPol.attributes.tnMonEPGPolName == 'check'
+ - '"tn-ansible_test/ap-anstest.json" in query_ap.url'
+ - query_ap_tenant is not changed
+ - query_ap_tenant.current | length == 1
+ - query_ap_tenant.current.0.fvTenant.children | length == 2
+ - '"rsp-subtree-class=fvAp" in query_ap_tenant.filter_string'
+ - '"tn-ansible_test.json" in query_ap_tenant.url'
+ - query_ap_ap is not changed
+ - query_ap_ap.current != []
+ - query_ap_ap.current.0.fvAp is defined
+ - '"query-target-filter=eq(fvAp.name,\"anstest\")" in query_ap_ap.filter_string'
+ - '"class/fvAp.json" in query_ap_ap.url'
+ - query_all is not changed
+ - query_all.current | length > 1
+ - '"class/fvAp.json" in query_all.url'
+
+ - name: delete ap - check_mode works
+ cisco.aci.aci_ap: &aci_ap_absent
+ <<: *aci_ap_present
+ state: absent
+ check_mode: true
+ register: ap_delete_check_mode
+
+ - name: delete ap - delete works
+ cisco.aci.aci_ap:
+ <<: *aci_ap_absent
+ register: ap_delete
+
+ - name: delete ap - delete idempotency works
+ cisco.aci.aci_ap:
+ <<: *aci_ap_absent
+ register: ap_delete_idempotent
+
+ - name: delete ap - missing param error
+ cisco.aci.aci_ap:
+ <<: *aci_ap_absent
+ tenant: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: ap_delete_missing_param
+
+ - name: delete ap remove ap used for query
+ cisco.aci.aci_ap:
+ <<: *aci_ap_absent
+ ap: anstest2
+
+ - name: absent assertions
+ assert:
+ that:
+ - ap_delete_check_mode is changed
+ - ap_delete_check_mode.previous != []
+ - '"tn-ansible_test/ap-anstest.json" in ap_delete_check_mode.url'
+ - ap_delete is changed
+ - ap_delete.previous == ap_delete_check_mode.previous
+ - ap_delete_idempotent is not changed
+ - ap_delete_idempotent.previous == []
+ - ap_delete_missing_param is failed
+ - 'ap_delete_missing_param.msg == "state is absent but all of the following are missing: tenant"'
+
+ - 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_bd/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/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/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml
new file mode 100644
index 000000000..3af05fd0f
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml
@@ -0,0 +1,312 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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
+ register: tenant_present
+
+ - name: ensure vrf exists for tests to kick off
+ cisco.aci.aci_vrf: &aci_vrf_present
+ <<: *aci_tenant_present
+ vrf: anstest
+ register: vrf_present
+
+ - name: ensure bd anstest does not exist
+ cisco.aci.aci_bd:
+ <<: *aci_tenant_present
+ bd: anstest
+ state: absent
+
+ - name: ensure bd anstest2 does not exist
+ cisco.aci.aci_bd:
+ <<: *aci_tenant_present
+ bd: anstest2
+ state: absent
+
+ - name: ensure L3out exists
+ cisco.aci.aci_l3out: &aci_l3_out_present
+ <<: *aci_tenant_present
+ tenant: ansible_test
+ l3out: ansible_l3out
+ domain: ansible_dom
+ route_control: export
+ vrf: anstest
+ l3protocol: ospf
+ state: present
+
+ - name: create bd - check mode works
+ cisco.aci.aci_bd: &aci_bd_present
+ <<: *aci_tenant_present
+ bd: anstest
+ description: Ansible Test
+ check_mode: true
+ register: bd_present_check_mode
+
+ - name: create bd - creation works
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ register: bd_present
+
+ - name: create bd again - idempotency works
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ register: bd_present_idempotent
+
+ - name: update bd - update works
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ vrf: anstest
+ description: Ansible Test Update
+ register: bd_update
+
+ - name: create another bd - check more params
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ bd: anstest2
+ bd_type: ethernet
+ endpoint_move_detect: default
+ ip_learning: "no"
+ l2_unknown_unicast: flood
+ l3_unknown_multicast: opt-flood
+ multi_dest: drop
+ enable_routing: "no"
+ arp_flooding: "yes"
+ route_profile_l3out: ansible_l3out
+ route_profile: ansible_l3out_route
+ register: bd_present_2
+ when: version.current.0.topSystem.attributes.version is version('4.2', '<')
+
+ - name: create another bd - check more params (>v4.2)
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ bd: anstest2
+ bd_type: ethernet
+ endpoint_move_detect: default
+ ip_learning: "no"
+ l2_unknown_unicast: flood
+ l3_unknown_multicast: opt-flood
+ ipv6_l3_unknown_multicast: opt-flood
+ multi_dest: drop
+ enable_routing: "no"
+ arp_flooding: "yes"
+ route_profile_l3out: ansible_l3out
+ route_profile: ansible_l3out_route
+ register: bd_present_2b
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+
+ - name: create bd without all necessary params - failure message works
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ tenant: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: bd_present_missing_param
+
+ - name: present asserts (<v4.2)
+ assert:
+ that:
+ - bd_present_check_mode is changed
+ - bd_present_check_mode.sent.fvBD.attributes.descr == 'Ansible Test'
+ - bd_present_check_mode.sent.fvBD.attributes.name == 'anstest'
+ - bd_present is changed
+ - bd_present.current.0.fvBD.attributes.annotation == 'orchestrator:ansible'
+ - bd_present.sent == bd_present_check_mode.sent
+ - bd_present.previous == []
+ - bd_present_idempotent is not changed
+ - bd_present_idempotent.previous != []
+ - bd_update is changed
+ - bd_update.previous != []
+ - bd_update.sent != bd_update.proposed
+ - bd_update.sent.fvBD.attributes.descr == 'Ansible Test Update'
+ - bd_update.sent.fvBD.children.0.fvRsCtx.attributes.tnFvCtxName == 'anstest'
+ - bd_present_2.sent.fvBD.attributes.arpFlood == 'yes'
+ - bd_present_2.sent.fvBD.attributes.descr == 'Ansible Test'
+ - bd_present_2.sent.fvBD.attributes.ipLearning == 'no'
+ - bd_present_2.sent.fvBD.attributes.multiDstPktAct == 'drop'
+ - bd_present_2.sent.fvBD.attributes.name == 'anstest2'
+ - bd_present_2.sent.fvBD.attributes.unicastRoute == 'no'
+ - bd_present_2.sent.fvBD.attributes.unkMacUcastAct == 'flood'
+ - bd_present_2.sent.fvBD.attributes.unkMcastAct == 'opt-flood'
+ - bd_present_2.sent.fvBD.attributes.type == 'regular'
+ - bd_present_2.sent.fvBD.children.0.fvRsBDToProfile.attributes.tnL3extOutName == 'ansible_l3out'
+ - bd_present_2.sent.fvBD.children.0.fvRsBDToProfile.attributes.tnRtctrlProfileName == 'ansible_l3out_route'
+ - bd_present_missing_param is failed
+ - 'bd_present_missing_param.msg == "state is present but all of the following are missing: tenant"'
+ when: version.current.0.topSystem.attributes.version is version('4.2', '<')
+
+ - name: present asserts (>v4.2)
+ assert:
+ that:
+ - bd_present_check_mode is changed
+ - bd_present_check_mode.sent.fvBD.attributes.descr == 'Ansible Test'
+ - bd_present_check_mode.sent.fvBD.attributes.name == 'anstest'
+ - bd_present is changed
+ - bd_present.sent == bd_present_check_mode.sent
+ - bd_present.previous == []
+ - bd_present_idempotent is not changed
+ - bd_present_idempotent.previous != []
+ - bd_update is changed
+ - bd_update.previous != []
+ - bd_update.sent != bd_update.proposed
+ - bd_update.sent.fvBD.attributes.descr == 'Ansible Test Update'
+ - bd_update.sent.fvBD.children.0.fvRsCtx.attributes.tnFvCtxName == 'anstest'
+ - bd_present_2b.sent.fvBD.attributes.arpFlood == 'yes'
+ - bd_present_2b.sent.fvBD.attributes.descr == 'Ansible Test'
+ - bd_present_2b.sent.fvBD.attributes.ipLearning == 'no'
+ - bd_present_2b.sent.fvBD.attributes.multiDstPktAct == 'drop'
+ - bd_present_2b.sent.fvBD.attributes.name == 'anstest2'
+ - bd_present_2b.sent.fvBD.attributes.unicastRoute == 'no'
+ - bd_present_2b.sent.fvBD.attributes.unkMacUcastAct == 'flood'
+ - bd_present_2b.sent.fvBD.attributes.unkMcastAct == 'opt-flood'
+ - bd_present_2b.sent.fvBD.attributes.v6unkMcastAct == 'opt-flood'
+ - bd_present_2b.sent.fvBD.attributes.type == 'regular'
+ - bd_present_2b.sent.fvBD.children.0.fvRsBDToProfile.attributes.tnL3extOutName == 'ansible_l3out'
+ - bd_present_2b.sent.fvBD.children.0.fvRsBDToProfile.attributes.tnRtctrlProfileName == 'ansible_l3out_route'
+ - bd_present_missing_param is failed
+ - 'bd_present_missing_param.msg == "state is present but all of the following are missing: tenant"'
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+
+ - name: get all bd
+ cisco.aci.aci_bd: &aci_query
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fake_var | default(omit) }}"
+ register: query_all
+
+ - name: get all in tenant
+ cisco.aci.aci_bd:
+ <<: *aci_query
+ tenant: ansible_test
+ register: query_tenant
+
+ - name: get all with name
+ cisco.aci.aci_bd:
+ <<: *aci_query
+ bd: anstest
+ register: query_bd_bd
+
+ - name: get bd
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ state: query
+ register: query_bd
+
+ - name: query asserts
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current | length > 1
+ - query_all.current.0.fvBD is defined
+ - '"rsp-subtree-class=fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_all.filter_string'
+ - '"class/fvBD.json" in query_all.url'
+ - query_tenant is not changed
+ - query_tenant.current | length == 1
+ - query_tenant.current.0.fvTenant.children | length == 2
+ - '"rsp-subtree-class=fvBD,fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_tenant.filter_string'
+ - '"tn-ansible_test.json" in query_tenant.url'
+ - query_bd_bd is not changed
+ - query_bd_bd.current != []
+ - '"query-target-filter=eq(fvBD.name,\"anstest\")" in query_bd_bd.filter_string'
+ - '"rsp-subtree-class=fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_bd_bd.filter_string'
+ - '"class/fvBD.json" in query_bd_bd.url'
+ - query_bd is not changed
+ - query_bd.current | length == 1
+ - query_bd.current.0.fvBD.attributes.name == "anstest"
+ - '"rsp-subtree-class=fvRsBDToNdP,fvRsBDToProfile,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_bd.filter_string'
+ - '"tn-ansible_test/BD-anstest.json" in query_bd.url'
+
+ - name: delete bd - check mode works
+ cisco.aci.aci_bd: &aci_bd_absent
+ <<: *aci_bd_present
+ state: absent
+ check_mode: true
+ register: bd_absent_check_mode
+
+ - name: delete bd - delete works
+ cisco.aci.aci_bd:
+ <<: *aci_bd_absent
+ register: bd_absent
+
+ - name: delete bd again - idempotency works
+ cisco.aci.aci_bd:
+ <<: *aci_bd_absent
+ register: bd_absent_idempotent
+
+ - name: delete bd - cleanup
+ cisco.aci.aci_bd:
+ <<: *aci_bd_absent
+ bd: anstest2
+
+ - name: delete bd missing param - fails properly
+ cisco.aci.aci_bd:
+ <<: *aci_bd_absent
+ bd: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: bd_absent_missing_param
+
+ - name: asserts for deletion task
+ assert:
+ that:
+ - bd_absent_check_mode is changed
+ - bd_absent_check_mode.proposed == {}
+ - bd_absent is changed
+ - bd_absent.previous != []
+ - bd_absent_idempotent is not changed
+ - bd_absent_idempotent.previous == []
+ - bd_absent_missing_param is failed
+ - 'bd_absent_missing_param.msg == "state is absent but all of the following are missing: bd"'
+
+ - name: delete vrf - cleanup before ending tests
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ state: absent
+ when: vrf_present is changed
+
+ - name: delete l3out - cleanup before ending tests
+ cisco.aci.aci_l3out:
+ <<: *aci_l3_out_present
+ state: absent
+
+ - 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_bd_dhcp_label/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/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_dhcp_label/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml
new file mode 100644
index 000000000..937ea80a3
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml
@@ -0,0 +1,154 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: create bd - creation works
+ aci_bd:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: database
+ register: bd_present
+
+ #CREATE LABELS
+ - name: Create a new DHCP Relay Label to a Bridge Domain - check mode
+ aci_bd_dhcp_label:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: database
+ dhcp_label: label1
+ owner: infra
+ state: present
+ check_mode: true
+ register: cm_dhcp_label1
+
+ - name: Verify creation of label1 in check mode
+ assert:
+ that:
+ - cm_dhcp_label1 is changed
+ - cm_dhcp_label1.sent.dhcpLbl.attributes.name == 'label1'
+
+ - name: Create a new DHCP Relay Label to a Bridge Domain - normal mode
+ aci_bd_dhcp_label:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: database
+ dhcp_label: label1
+ owner: infra
+ state: present
+ register: nm_dhcp_label1
+
+ - name: Verify creation of label1
+ assert:
+ that:
+ - nm_dhcp_label1 is changed
+ - nm_dhcp_label1.current.0.dhcpLbl.attributes.dn == 'uni/tn-ansible_tenant/BD-database/dhcplbl-label1'
+ - nm_dhcp_label1.current.0.dhcpLbl.attributes.name == 'label1'
+ - nm_dhcp_label1.current.0.dhcpLbl.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Create another DHCP Relay Label to a Bridge Domain - normal mode
+ aci_bd_dhcp_label:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: database
+ dhcp_label: label2
+ owner: infra
+ state: present
+ register: nm_dhcp_label2
+
+ - name: Verify creation of label2
+ assert:
+ that:
+ - nm_dhcp_label2 is changed
+ - nm_dhcp_label2.current.0.dhcpLbl.attributes.dn == 'uni/tn-ansible_tenant/BD-database/dhcplbl-label2'
+ - nm_dhcp_label2.current.0.dhcpLbl.attributes.name == 'label2'
+
+ #QUERY LABELS
+ - name: Query a DHCP Relay Label of a Bridge Domain
+ aci_bd_dhcp_label:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: database
+ dhcp_label: label1
+ owner: infra
+ state: query
+ register: query_dhcp_label1
+
+ - name: Verify query of label
+ assert:
+ that:
+ - query_dhcp_label1 is not changed
+ - query_dhcp_label1.current.0.dhcpLbl.attributes.dn == 'uni/tn-ansible_tenant/BD-database/dhcplbl-label1'
+
+ - name: Query all DHCP Relay Labels of a Bridge Domain
+ aci_bd_dhcp_label:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: database
+ state: query
+ register: query_all_labels
+
+ - name: Verify query all of labels
+ assert:
+ that:
+ - query_all_labels is not changed
+
+ #REMOVE LABELS
+ - name: Remove a DHCP Relay Label for a Bridge Domain
+ aci_bd_dhcp_label:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: database
+ dhcp_label: label1
+ owner: infra
+ state: absent
+ register: delete_dhcp_label
+
+ - name: Verify deletion of label
+ assert:
+ that:
+ - delete_dhcp_label is changed
+ - delete_dhcp_label.current == []
+
+ # CLEAN ENVIRONMENT AGAIN
+ - name: Remove the ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_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_bd_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml
new file mode 100644
index 000000000..10f00990c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml
@@ -0,0 +1,247 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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
+ 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
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: ensure bd exists for tests to kick off
+ cisco.aci.aci_bd: &aci_bd_present
+ <<: *aci_tenant_present
+ bd: anstest
+ register: bd_present
+
+ - name: ensure subnet does not exist for tests to kick off
+ cisco.aci.aci_bd_subnet: &aci_subnet_absent
+ <<: *aci_bd_present
+ state: absent
+ gateway: 10.100.100.1
+ mask: 24
+
+ - name: ensure subnet does not exist for tests to kick off
+ cisco.aci.aci_bd_subnet: &aci_subnet2_absent
+ <<: *aci_subnet_absent
+ gateway: 10.100.101.1
+ mask: 25
+
+ - name: create subnet - check mode works
+ cisco.aci.aci_bd_subnet: &aci_subnet_present
+ <<: *aci_subnet_absent
+ state: present
+ subnet_name: anstest
+ descr: Ansible Test
+ check_mode: true
+ register: create_check_mode
+
+ - name: create subnet - creation works
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet_present
+ register: create_subnet
+
+ - name: create new subnet - creation works
+ cisco.aci.aci_bd_subnet: &aci_subnet2_present
+ <<: *aci_subnet2_absent
+ state: present
+ descr: Ansible Test
+ scope: [private, shared]
+ route_profile: default
+ route_profile_l3_out: default
+ register: create_subnet2
+
+ - name: create subnet again - idempotency works
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet2_present
+ register: create_idempotency
+
+ - name: modify subnet - update works
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet_present
+ scope: [shared, public]
+ subnet_control: querier_ip
+ register: modify_subnet
+
+ - name: create subnet with bad scope - failure message works
+ cisco.aci.aci_bd_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_bd_subnet:
+ <<: *aci_subnet_present
+ bd: "{{ fake_var | default(omit) }}"
+ register: create_incomplete_data
+ 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_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
+ - modify_subnet.previous != []
+ - modify_subnet.sent != modify_subnet.proposed
+ - modify_subnet.sent.fvSubnet.attributes.ctrl == 'querier'
+ - modify_subnet.sent.fvSubnet.attributes.scope == 'public,shared'
+ - 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: bd"'
+
+ - name: get all subnets
+ cisco.aci.aci_bd_subnet: &aci_query
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fake_var | default(omit) }}"
+ register: get_all
+
+ - name: get all in tenant
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_query
+ tenant: ansible_test
+ register: get_all_tenant
+
+ - name: get all in bd
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_query
+ bd: anstest
+ register: get_all_bd
+
+ - name: get all tenant and bd
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_bd_present
+ state: query
+ register: get_all_tenant_bd
+
+ - name: get subnet in tenant
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet_present
+ state: query
+ bd: "{{ fake_var | default(omit) }}"
+ register: get_subnet_tenant
+
+ - name: get subnet in bd
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet_present
+ state: query
+ tenant: "{{ fake_var | default(omit) }}"
+ register: get_subnet_bd
+
+ - name: get specific subnet
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet_present
+ state: query
+ register: get_subnet
+
+ - name: get all subnets matching gateway
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet_present
+ state: query
+ tenant: "{{ fake_var | default(omit) }}"
+ bd: "{{ fake_var | default(omit) }}"
+ register: get_subnets_gateway
+
+ - name: asserts for query tasks
+ assert:
+ that:
+ - get_all is not changed
+ - get_all.current | length > 1
+ - get_all_tenant is not changed
+ - '"tn-ansible_test.json" in get_all_tenant.url'
+ - get_all_bd is not changed
+ - '"query-target-filter=eq(fvBD.name,\"anstest\")" in get_all_bd.filter_string'
+ - '"class/fvBD.json" in get_all_bd.url'
+ - get_all_tenant_bd is not changed
+ - '"tn-ansible_test/BD-anstest.json" in get_all_tenant_bd.url'
+ - get_all_tenant_bd.current.0.fvBD.children | length > 1
+ - get_subnet_tenant is not changed
+ - '"rsp-subtree-filter=eq(fvSubnet.ip,\"10.100.100.1/24\")" in get_subnet_tenant.filter_string'
+ - '"tn-ansible_test.json" in get_subnet_tenant.url'
+ - get_subnet_bd is not changed
+ - '"query-target-filter=eq(fvBD.name,\"anstest\")"'
+ - '"rsp-subtree-filter=eq(fvSubnet.ip,\"10.100.100.1/24\")" in get_subnet_bd.filter_string'
+ - '"class/fvBD.json" in get_subnet_bd.url'
+ - get_subnet is not changed
+ - get_subnet.current | length == 1
+ - '"tn-ansible_test/BD-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_bd_subnet:
+ <<: *aci_subnet_absent
+ check_mode: true
+ register: delete_check_mode
+
+ - name: delete subnet - delete works
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet_absent
+ register: delete_subnet
+
+ - name: delete subnet - cleanup
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet2_absent
+
+ - name: delete subnet again - idempotency works
+ cisco.aci.aci_bd_subnet:
+ <<: *aci_subnet2_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 bd - cleanup before ending tests
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ state: absent
+ when: bd_present is changed
+
+ - 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_bgp_rr_asn/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/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_rr_asn/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml
new file mode 100644
index 000000000..3b65520bc
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_asn/tasks/main.yml
@@ -0,0 +1,87 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove BGP Route Reflector ASN if it already exists
+ cisco.aci.aci_bgp_rr_asn:
+ <<: *aci_info
+ state: absent
+
+# ADD ROUTE REFLECTOR BGP ASN
+- name: Add BGP Route Reflector ASN
+ cisco.aci.aci_bgp_rr_asn:
+ <<: *aci_info
+ asn: 65001
+ state: present
+ register: add_bgp_rr_asn
+
+- name: Verify that BGP route reflector ASN has been created with correct attributes
+ assert:
+ that:
+ - add_bgp_rr_asn is changed
+ - add_bgp_rr_asn.current.0.bgpAsP.attributes.annotation == 'orchestrator:ansible'
+ - add_bgp_rr_asn.current.0.bgpAsP.attributes.dn == "uni/fabric/bgpInstP-default/as"
+ - add_bgp_rr_asn.current.0.bgpAsP.attributes.asn == "65001"
+
+# ADD ROUTE REFLECTOR ASN AGAIN TO TEST IDEMPOTENCE
+- name: Add BGP route reflector ASN again
+ cisco.aci.aci_bgp_rr_asn:
+ <<: *aci_info
+ asn: 65001
+ state: present
+ register: add_bgp_rr_asn_again
+
+- name: Verify that BGP route reflector ASN idempotence
+ assert:
+ that:
+ - add_bgp_rr_asn_again is not changed
+ - add_bgp_rr_asn_again.current.0.bgpAsP.attributes.dn == "uni/fabric/bgpInstP-default/as"
+ - add_bgp_rr_asn_again.current.0.bgpAsP.attributes.asn == "65001"
+
+# MODIFY ROUTE REFLECTOR ASN
+- name: Update BGP route reflector ASN
+ cisco.aci.aci_bgp_rr_asn:
+ <<: *aci_info
+ asn: 65002
+ state: present
+ register: update_bgp_rr_asn
+
+- name: Verify that BGP route reflector ASN has been updated with correct attributes
+ assert:
+ that:
+ - update_bgp_rr_asn is changed
+ - update_bgp_rr_asn.current.0.bgpAsP.attributes.dn == "uni/fabric/bgpInstP-default/as"
+ - update_bgp_rr_asn.current.0.bgpAsP.attributes.asn == "65002"
+
+# QUERY ROUTE REFLECTOR ASN
+- name: Query BGP route reflector ASN
+ cisco.aci.aci_bgp_rr_asn:
+ <<: *aci_info
+ state: query
+ register: query_bgp_rr_asn
+
+- name: Verify BGP route reflector ASN
+ assert:
+ that:
+ - query_bgp_rr_asn is not changed
+ - query_bgp_rr_asn.current.0.bgpAsP.attributes.dn == "uni/fabric/bgpInstP-default/as"
+ - query_bgp_rr_asn.current.0.bgpAsP.attributes.asn == "65002"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_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_bgp_rr_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/tasks/main.yml
new file mode 100644
index 000000000..d1ec77a27
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bgp_rr_node/tasks/main.yml
@@ -0,0 +1,132 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove BGP Route Reflector Node 101 if it already exists
+ cisco.aci.aci_bgp_rr_node:
+ <<: *aci_info
+ node_id: 101
+ state: absent
+
+# ADD ROUTE REFLECTOR NODE
+- name: Add BGP Route Reflector Node
+ cisco.aci.aci_bgp_rr_node:
+ <<: *aci_info
+ node_id: 101
+ pod_id: 1
+ description: ans_node
+ state: present
+ register: add_bgp_rr_node
+
+- name: Verify that BGP route reflector node has been created with correct attributes
+ assert:
+ that:
+ - add_bgp_rr_node is changed
+ - add_bgp_rr_node.current.0.bgpRRNodePEp.attributes.annotation == 'orchestrator:ansible'
+ - add_bgp_rr_node.current.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101"
+ - add_bgp_rr_node.current.0.bgpRRNodePEp.attributes.id == "101"
+ - add_bgp_rr_node.current.0.bgpRRNodePEp.attributes.podId == "1"
+ - add_bgp_rr_node.current.0.bgpRRNodePEp.attributes.descr == "ans_node"
+
+# ADD ROUTE REFLECTOR NODE AGAIN TO TEST IDEMPOTENCE
+- name: Add BGP route reflector node again
+ cisco.aci.aci_bgp_rr_node:
+ <<: *aci_info
+ node_id: 101
+ pod_id: 1
+ description: ans_node
+ state: present
+ register: add_bgp_rr_node_again
+
+- name: Verify that BGP route reflector node has been created with correct attributes
+ assert:
+ that:
+ - add_bgp_rr_node_again is not changed
+ - add_bgp_rr_node_again.current.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101"
+ - add_bgp_rr_node_again.current.0.bgpRRNodePEp.attributes.id == "101"
+ - add_bgp_rr_node_again.current.0.bgpRRNodePEp.attributes.podId == "1"
+ - add_bgp_rr_node_again.current.0.bgpRRNodePEp.attributes.descr == "ans_node"
+
+# MODIFY ROUTE REFLECTOR NODE
+- name: Add BGP route reflector node again
+ cisco.aci.aci_bgp_rr_node:
+ <<: *aci_info
+ node_id: 101
+ pod_id: 1
+ description: ans_node_update
+ state: present
+ register: update_bgp_rr_node
+
+- name: Verify that BGP route reflector node has been updated with correct attributes
+ assert:
+ that:
+ - update_bgp_rr_node is changed
+ - update_bgp_rr_node.current.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101"
+ - update_bgp_rr_node.current.0.bgpRRNodePEp.attributes.id == "101"
+ - update_bgp_rr_node.current.0.bgpRRNodePEp.attributes.podId == "1"
+ - update_bgp_rr_node.current.0.bgpRRNodePEp.attributes.descr == "ans_node_update"
+
+# QUERY ROUTE REFLECTOR NODE
+- name: Add BGP route reflector node again
+ cisco.aci.aci_bgp_rr_node:
+ <<: *aci_info
+ node_id: 101
+ state: query
+ register: query_bgp_rr_node
+
+- name: Verify that BGP route reflector node attributes
+ assert:
+ that:
+ - query_bgp_rr_node is not changed
+ - query_bgp_rr_node.current.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101"
+ - query_bgp_rr_node.current.0.bgpRRNodePEp.attributes.id == "101"
+ - query_bgp_rr_node.current.0.bgpRRNodePEp.attributes.podId == "1"
+ - query_bgp_rr_node.current.0.bgpRRNodePEp.attributes.descr == "ans_node_update"
+
+- name: Query all route relector nodes
+ cisco.aci.aci_bgp_rr_node:
+ <<: *aci_info
+ state: query
+ register: query_bgp_rr_node_all
+
+- name: Verify query_bgp_rr_node_all
+ assert:
+ that:
+ - query_bgp_rr_node_all is not changed
+
+# DELETE ROUTE REFLECTOR NODE
+- name: Remove BGP route reflector node
+ cisco.aci.aci_bgp_rr_node:
+ <<: *aci_info
+ node_id: 101
+ state: absent
+ register: remove_bgp_rr_node
+
+- name: Verify BGP route reflector node removal
+ assert:
+ that:
+ - remove_bgp_rr_node is changed
+ - remove_bgp_rr_node.current == []
+ - remove_bgp_rr_node.previous.0.bgpRRNodePEp.attributes.dn == "uni/fabric/bgpInstP-default/rr/node-101"
+ - remove_bgp_rr_node.previous.0.bgpRRNodePEp.attributes.id == "101"
+ - remove_bgp_rr_node.previous.0.bgpRRNodePEp.attributes.podId == "1"
+ - remove_bgp_rr_node.previous.0.bgpRRNodePEp.attributes.descr == "ans_node_update"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml
new file mode 100644
index 000000000..909cf933c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_bulk_static_binding_to_epg/tasks/main.yml
@@ -0,0 +1,772 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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
+
+- 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
+ - name: Ensure ansible_test tenant does not exists
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+
+ - name: Ensure ansible_test tenant exists
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Ensure anstest ap exists
+ cisco.aci.aci_ap: &ap_present
+ <<: *tenant_present
+ ap: anstest
+
+ - name: Ensure anstest epg exists
+ cisco.aci.aci_epg: &epg_present
+ <<: *ap_present
+ epg: anstest
+
+ - name: Add list of interfaces with check mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &cm_interfaces_present
+ <<: *epg_present
+ interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface_configs:
+ - interface: 1/7
+ leafs: 101
+ pod: 1
+ - interface: 1/7
+ leafs: 107
+ pod: 7
+ - interface: 1/8
+ leafs: 108
+ pod: 8
+ encap_id: 108
+ primary_encap_id: 1008
+ state: present
+ check_mode: true
+ register: cm_interfaces_present
+
+ - name: Assertions check for add list of interfaces with check mode
+ assert:
+ that:
+ - cm_interfaces_present is changed
+ - cm_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - "'children' not in cm_interfaces_present.previous.0.fvAEPg"
+ - "'children' not in cm_interfaces_present.current.0.fvAEPg"
+
+ - name: Add list of interfaces with normal mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &nm_interfaces_present
+ <<: *cm_interfaces_present
+ register: nm_interfaces_present
+
+ - name: Assertions check for add list of interfaces with normal mode
+ assert:
+ that:
+ - nm_interfaces_present is changed
+ - nm_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - nm_interfaces_present.current.0.fvAEPg.children | length == 3
+ - "'children' not in nm_interfaces_present.previous.0.fvAEPg"
+ - nm_interfaces_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == ""
+
+ - name: Add list of interfaces with normal mode - idempotency works
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *nm_interfaces_present
+ register: idempotency_interfaces_present
+
+ - name: Idempotency assertions check for add list of interfaces with normal mode
+ assert:
+ that:
+ - idempotency_interfaces_present is not changed
+ - idempotency_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - idempotency_interfaces_present.current.0.fvAEPg.children | length == 3
+ - idempotency_interfaces_present.previous.0.fvAEPg.children | length == 3
+
+ - name: Update list of interfaces - description with check mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &cm_update_interfaces_present
+ <<: *nm_interfaces_present
+ description: "Description set from module level attributes"
+ check_mode: true
+ register: cm_update_interfaces_present
+
+ - name: Assertions check for update list of interfaces - description with normal mode
+ assert:
+ that:
+ - cm_update_interfaces_present is changed
+ - cm_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - cm_update_interfaces_present.current.0.fvAEPg.children | length == 3
+ - cm_update_interfaces_present.previous.0.fvAEPg.children | length == 3
+ - cm_update_interfaces_present.previous.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == ""
+ - cm_update_interfaces_present.current.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == ""
+
+ - name: Update list of interfaces - description with normal mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &nm_update_interfaces_present
+ <<: *cm_update_interfaces_present
+ register: nm_update_interfaces_present
+
+ - name: Assertions check for update list of interfaces - description with normal mode
+ assert:
+ that:
+ - nm_update_interfaces_present is changed
+ - nm_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - nm_update_interfaces_present.current.0.fvAEPg.children | length == 3
+ - nm_update_interfaces_present.previous.0.fvAEPg.children | length == 3
+ - nm_update_interfaces_present.previous.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == ""
+ - nm_update_interfaces_present.current.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == "Description set from module level attributes"
+
+ - name: Update list of interfaces - description with normal mode - idempotency works
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *nm_update_interfaces_present
+ register: idempotency_nm_update_interfaces_present
+
+ - name: Idempotency assertions check for update list of interfaces - description with normal mode
+ assert:
+ that:
+ - idempotency_nm_update_interfaces_present is not changed
+ - idempotency_nm_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - idempotency_nm_update_interfaces_present.current.0.fvAEPg.children | length == 3
+ - idempotency_nm_update_interfaces_present.previous.0.fvAEPg.children | length == 3
+ - idempotency_nm_update_interfaces_present.current.0.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from module level attributes"
+ - idempotency_nm_update_interfaces_present.previous.0.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from module level attributes"
+
+ - name: Update list of interfaces description using path level attributes with check mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &cm_path_update_interfaces_present
+ <<: *epg_present
+ interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ interface_configs:
+ - interface: 1/7
+ leafs: 101
+ pod: 1
+ description: "Description set from path level attributes"
+ - interface: 1/7
+ leafs: 107
+ pod: 7
+ description: "Description set from path level attributes"
+ - interface: 1/8
+ leafs: 108
+ pod: 8
+ encap_id: 108
+ primary_encap_id: 1008
+ description: "Description set from path level attributes"
+ state: present
+ check_mode: true
+ register: cm_path_update_interfaces_present
+
+ - name: Assertions check for update list of interfaces description using path level attributes with check mode
+ assert:
+ that:
+ - cm_path_update_interfaces_present is changed
+ - cm_path_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - cm_path_update_interfaces_present.current.0.fvAEPg.children | length == 3
+ - cm_path_update_interfaces_present.previous.0.fvAEPg.children | length == 3
+ - cm_path_update_interfaces_present.current.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == "Description set from module level attributes"
+ - cm_path_update_interfaces_present.previous.0.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from module level attributes"
+ - cm_path_update_interfaces_present.sent.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+
+ - name: Update list of interfaces description using path level attributes with normal mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &nm_path_update_interfaces_present
+ <<: *cm_path_update_interfaces_present
+ register: nm_path_update_interfaces_present
+
+ - name: Assertions check for update list of interfaces description using path level attributes with normal mode
+ assert:
+ that:
+ - nm_path_update_interfaces_present is changed
+ - nm_path_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - nm_path_update_interfaces_present.current.0.fvAEPg.children | length == 3
+ - nm_path_update_interfaces_present.previous.0.fvAEPg.children | length == 3
+ - nm_path_update_interfaces_present.current.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+ - nm_path_update_interfaces_present.previous.0.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from module level attributes"
+
+ - name: Update list of interfaces description using path level attributes with normal mode - idempotency works
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *nm_path_update_interfaces_present
+ register: idempotency_path_update_interfaces_present
+
+ - name: Idempotency assertions check for update list of interfaces description using path level attributes with normal mode
+ assert:
+ that:
+ - idempotency_path_update_interfaces_present is not changed
+ - idempotency_path_update_interfaces_present.current.0.fvAEPg.attributes.name == "anstest"
+ - idempotency_path_update_interfaces_present.current.0.fvAEPg.children | length == 3
+ - idempotency_path_update_interfaces_present.previous.0.fvAEPg.children | length == 3
+ - idempotency_path_update_interfaces_present.current.0.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+
+ - name: Query all interfaces of an EPG
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ epg: anstest
+ state: query
+ register: query_result_of_anstest_epg
+
+ - name: Assertions check for query all interfaces of an EPG
+ assert:
+ that:
+ - query_result_of_anstest_epg is not changed
+ - query_result_of_anstest_epg.current.0.fvAEPg.children | length == 3
+ - query_result_of_anstest_epg.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+ - query_result_of_anstest_epg.current.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+ - query_result_of_anstest_epg.current.0.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+
+ - name: Query all interfaces
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *aci_info
+ state: query
+ register: query_all_interfaces
+
+ - name: Assertions check for query all interfaces # Check covers only EPG level
+ assert:
+ that:
+ - query_all_interfaces is not changed
+ - query_all_interfaces.current | length >= 1
+
+ - name: Remove list of interfaces with check mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &cm_interfaces_absent
+ <<: *cm_interfaces_present
+ state: absent
+ check_mode: true
+ register: cm_interfaces_absent
+
+ - name: Assertions check for remove list of interfaces with check mode
+ assert:
+ that:
+ - cm_interfaces_absent is changed
+ - cm_interfaces_absent.current.0.fvAEPg.children | length == 3
+ - cm_interfaces_absent.current.0.fvAEPg.attributes.name == "anstest"
+ - cm_interfaces_absent.previous.0.fvAEPg.children | length == 3
+ - cm_interfaces_absent.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+ - cm_interfaces_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+
+ - name: Remove list of interfaces with normal mode
+ cisco.aci.aci_bulk_static_binding_to_epg: &nm_interfaces_absent
+ <<: *cm_interfaces_absent
+ register: nm_interfaces_absent
+
+ - name: Assertions check for remove list of interfaces with normal mode
+ assert:
+ that:
+ - nm_interfaces_absent is changed
+ - "'children' not in nm_interfaces_absent.current.0.fvAEPg"
+ - nm_interfaces_absent.current.0.fvAEPg.attributes.name == "anstest"
+ - nm_interfaces_absent.previous.0.fvAEPg.children | length == 3
+ - nm_interfaces_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+ - nm_interfaces_absent.previous.0.fvAEPg.children.1.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+ - nm_interfaces_absent.previous.0.fvAEPg.children.2.fvRsPathAtt.attributes.descr == "Description set from path level attributes"
+
+ - name: Remove list of interfaces with normal mode - idempotency works
+ cisco.aci.aci_bulk_static_binding_to_epg: &idempotency_interfaces_absent
+ <<: *nm_interfaces_absent
+ register: idempotency_interfaces_absent
+
+ - name: Idempotency assertions check for remove list of interfaces with normal mode
+ assert:
+ that:
+ - idempotency_interfaces_absent is changed
+ - "'children' not in idempotency_interfaces_absent.current.0.fvAEPg"
+ - "'children' not in idempotency_interfaces_absent.previous.0.fvAEPg"
+ - idempotency_interfaces_absent.current.0.fvAEPg.attributes.name == "anstest"
+
+ - name: Add fex_port_channel interfaces to anstest epg
+ cisco.aci.aci_bulk_static_binding_to_epg: &fex_port_channel_present
+ <<: *epg_present
+ interface_mode: trunk
+ interface_type: fex_port_channel
+ deploy_immediacy: lazy
+ descr: "fex_port_channel - interface created"
+ encap_id: 222
+ interface_configs:
+ - extpaths:
+ - 1012
+ interface: 2/7
+ leafs: 102
+ pod: 2
+ register: fex_port_channel_present
+
+ - name: Assertions check for add fex_port_channel interfaces to anstest epg
+ assert:
+ that:
+ - fex_port_channel_present is changed
+ - fex_port_channel_present.current.0.fvAEPg.children | length == 1
+ - '"children" not in fex_port_channel_present.previous.0.fvAEPg'
+ - fex_port_channel_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-222"
+ - fex_port_channel_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-2/paths-102/extpaths-1012/pathep-[2/7]"
+ - fex_port_channel_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "fex_port_channel - interface created"
+
+ - name: Remove fex_port_channel interfaces from anstest epg
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_port_channel_present
+ state: absent
+ register: fex_port_channel_absent
+
+ - name: Assertions check for remove fex_port_channel interfaces from anstest epg
+ assert:
+ that:
+ - fex_port_channel_absent is changed
+ - fex_port_channel_absent.previous.0.fvAEPg.children | length == 1
+ - "'children' not in fex_port_channel_absent.current.0.fvAEPg"
+ - fex_port_channel_absent.previous.0.fvAEPg.attributes.name == "anstest"
+ - fex_port_channel_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-222"
+ - fex_port_channel_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-2/paths-102/extpaths-1012/pathep-[2/7]"
+
+ - name: Add fex_vpc interfaces to anstest epg
+ cisco.aci.aci_bulk_static_binding_to_epg: &fex_vpc_present
+ <<: *epg_present
+ interface_mode: trunk
+ interface_type: fex_vpc
+ deploy_immediacy: lazy
+ descr: fex_vpc - interface created
+ encap_id: 223
+ interface_configs:
+ - extpaths:
+ - 103
+ - 104
+ interface: 3/7
+ leafs:
+ - 103
+ - 104
+ pod: 3
+ register: fex_vpc_present
+
+ - name: Assertions check for add fex_vpc interfaces to anstest epg
+ assert:
+ that:
+ - fex_vpc_present is changed
+ - fex_vpc_present.current.0.fvAEPg.children | length == 1
+ - "'children' not in fex_vpc_present.previous.0.fvAEPg"
+ - fex_vpc_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "fex_vpc - interface created"
+ - fex_vpc_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-223"
+ - fex_vpc_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-3/protpaths-103-104/extprotpaths-103-104/pathep-[3/7]"
+
+ - name: Remove fex_vpc interfaces from anstest epg
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_present
+ state: absent
+ register: fex_vpc_absent
+
+ - name: Assertions check for remove fex_vpc interfaces from anstest epg
+ assert:
+ that:
+ - fex_vpc_absent is changed
+ - fex_vpc_absent.previous.0.fvAEPg.children | length == 1
+ - "'children' not in fex_vpc_absent.current.0.fvAEPg"
+ - fex_vpc_absent.previous.0.fvAEPg.attributes.name == "anstest"
+ - fex_vpc_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-223"
+ - fex_vpc_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-3/protpaths-103-104/extprotpaths-103-104/pathep-[3/7]"
+
+ - name: Add vpc interfaces to anstest epg
+ cisco.aci.aci_bulk_static_binding_to_epg: &vpc_present
+ <<: *epg_present
+ deploy_immediacy: lazy
+ descr: vpc - interface created
+ interface_mode: trunk
+ interface_type: vpc
+ encap_id: 224
+ interface_configs:
+ - interface: 4/7
+ leafs:
+ - 105
+ - 106
+ pod: 4
+ extpaths:
+ - 1015
+ register: vpc_present
+
+ - name: Assertions check for add vpc interfaces to anstest epg
+ assert:
+ that:
+ - vpc_present is changed
+ - vpc_present.current.0.fvAEPg.children | length == 1
+ - "'children' not in vpc_present.previous.0.fvAEPg"
+ - vpc_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "vpc - interface created"
+ - vpc_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-224"
+ - vpc_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-4/protpaths-105-106/pathep-[4/7]"
+
+ - name: Remove vpc interfaces from anstest epg
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *vpc_present
+ state: absent
+ register: vpc_absent
+
+ - name: Assertions check for remove vpc interfaces from anstest epg
+ assert:
+ that:
+ - vpc_absent is changed
+ - vpc_absent.previous.0.fvAEPg.children | length == 1
+ - "'children' not in vpc_absent.current.0.fvAEPg"
+ - vpc_absent.previous.0.fvAEPg.attributes.name == "anstest"
+ - vpc_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-224"
+ - vpc_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-4/protpaths-105-106/pathep-[4/7]"
+
+ - name: Query all interfaces before start module and path level check
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ epg: anstest
+ state: query
+ register: query_result
+
+ - name: Assertions check for query all interfaces before start module and path level check
+ assert:
+ that:
+ - query_result is not changed
+ - "'children' not in query_result.current.0.fvAEPg"
+ - query_result.current.0.fvAEPg.attributes.name == "anstest"
+
+ - name: Add an interface with module level attributes
+ cisco.aci.aci_bulk_static_binding_to_epg: &module_level_check_present
+ <<: *epg_present
+ interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 108
+ primary_encap_id: unknown
+ description: "Module level test"
+ interface_configs:
+ - interface: 1/8
+ leafs: 108
+ pod: 8
+ state: present
+ register: module_level_check
+
+ - name: Assertions check for add an interface with module level attributes
+ assert:
+ that:
+ - module_level_check is changed
+ - module_level_check.current.0.fvAEPg.children | length == 1
+ - module_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-108"
+ - module_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.primaryEncap == "unknown"
+ - module_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-8/paths-108/pathep-[eth1/8]"
+ - module_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Module level test"
+ - module_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.instrImedcy == "lazy"
+ - module_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.mode == "regular"
+
+ - name: Remove an interface with module level attributes
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *module_level_check_present
+ state: absent
+ register: module_level_check_absent
+
+ - name: Assertions check for remove an interface with module level attributes
+ assert:
+ that:
+ - module_level_check_absent is changed
+ - "'children' not in module_level_check_absent.current.0.fvAEPg"
+ - module_level_check_absent.current.0.fvAEPg.attributes.name == "anstest"
+ - module_level_check_absent.previous.0.fvAEPg.children | length == 1
+ - module_level_check_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-108"
+ - module_level_check_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.primaryEncap == "unknown"
+ - module_level_check_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Module level test"
+ - module_level_check_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-8/paths-108/pathep-[eth1/8]"
+
+ - name: Add an interface with path level attributes
+ cisco.aci.aci_bulk_static_binding_to_epg: &path_level_check_present
+ <<: *epg_present
+ interface_configs:
+ - interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 109
+ description: "Path level test"
+ interface: 1/9
+ leafs: 109
+ pod: 9
+ state: present
+ register: path_level_check
+
+ - name: Assertions check for add an interface with path level attributes
+ assert:
+ that:
+ - path_level_check is changed
+ - path_level_check.current.0.fvAEPg.children | length == 1
+ - path_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-109"
+ - path_level_check.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-9/paths-109/pathep-[eth1/9]"
+
+ - name: Remove an interface with path level attributes
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *path_level_check_present
+ state: absent
+ register: path_level_check_absent
+
+ - name: Assertions check for remove an interface with path level attributes
+ assert:
+ that:
+ - path_level_check_absent is changed
+ - "'children' not in path_level_check_absent.current.0.fvAEPg"
+ - path_level_check_absent.current.0.fvAEPg.attributes.name == "anstest"
+ - path_level_check_absent.previous.0.fvAEPg.children | length == 1
+ - path_level_check_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-109"
+ - path_level_check_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Path level test"
+ - path_level_check_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-9/paths-109/pathep-[eth1/9]"
+
+ - name: Add an interface encap_id with path and module level attributes
+ cisco.aci.aci_bulk_static_binding_to_epg: &path_and_module_encap_id_present
+ <<: *epg_present
+ encap_id: 108
+ interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ description: "Path and Module level test"
+ interface_configs:
+ - interface: 1/7
+ leafs: 107
+ pod: 7
+ encap_id: 107
+ state: present
+ register: path_and_module_encap_id_present
+
+ - name: Assertions check for add an interface encap_id with path and module level attributes
+ assert:
+ that:
+ - path_and_module_encap_id_present is changed
+ - path_and_module_encap_id_present.current.0.fvAEPg.children | length == 1
+ - path_and_module_encap_id_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-107"
+ - path_and_module_encap_id_present.current.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-7/paths-107/pathep-[eth1/7]"
+
+ - name: Remove an interface encap_id with path and module level attributes
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *path_and_module_encap_id_present
+ state: absent
+ register: path_and_module_encap_id_absent
+
+ - name: Assertions check for remove an interface encap_id with path and module level attributes
+ assert:
+ that:
+ - path_and_module_encap_id_absent is changed
+ - "'children' not in path_and_module_encap_id_absent.current.0.fvAEPg"
+ - path_and_module_encap_id_absent.current.0.fvAEPg.attributes.name == "anstest"
+ - path_and_module_encap_id_absent.previous.0.fvAEPg.children | length == 1
+ - path_and_module_encap_id_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.encap == "vlan-107"
+ - path_and_module_encap_id_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.descr == "Path and Module level test"
+ - path_and_module_encap_id_absent.previous.0.fvAEPg.children.0.fvRsPathAtt.attributes.tDn == "topology/pod-7/paths-107/pathep-[eth1/7]"
+
+ - name: Bind static-binding to epg - interface type switch_port - no leafs (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *epg_present
+ interface_configs:
+ - interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ pod: 1
+ state: present
+ ignore_errors: true
+ register: switch_port_no_leafs
+
+ - name: Bind static-binding to epg - interface type fex_vpc - no extpaths (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg: &fex_vpc_no_extpaths
+ <<: *epg_present
+ interface_configs:
+ - interface_type: fex_vpc
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ leafs: 101
+ pod: 1
+ state: present
+ ignore_errors: true
+ register: fex_vpc_no_extpaths
+
+ - name: Bind static-binding to epg - interface type fex_vpc - incorrect extpaths (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: fex_vpc
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ leafs: 101
+ pod: 1
+ extpaths:
+ - 1012
+ ignore_errors: true
+ register: fex_vpc_one_node
+
+ - name: Bind static-binding to epg - fex_vpc with one extpaths (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: fex_vpc
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ - 102
+ extpaths:
+ - 103
+ ignore_errors: true
+ register: fex_vpc_one_extpaths
+
+ - name: Bind static-binding to epg - switch_port with two leafs (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ - 102
+ ignore_errors: true
+ register: switch_port_two_leafs
+
+ - name: Bind static-binding to epg - switch_port with two extpaths (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ extpaths:
+ - 102
+ - 103
+ ignore_errors: true
+ register: switch_port_two_extpaths
+
+ - name: Bind static-binding to epg - fex_vpc with 3 nodes (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: fex_vpc
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ - 102
+ - 103
+ extpaths:
+ - 101
+ - 102
+ ignore_errors: true
+ register: fex_vpc_three_leafs
+
+ - name: Bind static-binding to epg - fex_vpc with 3 expaths (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: fex_vpc
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ - 102
+ extpaths:
+ - 101
+ - 102
+ - 103
+ ignore_errors: true
+ register: fex_vpc_three_expaths
+
+ - name: Bind static-binding to epg - switch_port with encap_id 5000 (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 5000
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ ignore_errors: true
+ register: switch_port_encap_id_too_high
+
+ - name: Bind static-binding to epg - switch_port with primary_encap_id 5000 (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ primary_encap_id: 5000
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ ignore_errors: true
+ register: switch_port_primary_encap_id_too_high
+
+ - name: Bind static-binding to epg - switch_port with primary_encap_id 5000 (normal mode)
+ cisco.aci.aci_bulk_static_binding_to_epg:
+ <<: *fex_vpc_no_extpaths
+ interface_configs:
+ - interface_type: switch_port
+ interface_mode: trunk
+ deploy_immediacy: lazy
+ encap_id: 107
+ primary_encap_id: not_unknown
+ interface: 'ansible_test'
+ pod: 1
+ leafs:
+ - 101
+ ignore_errors: true
+ register: switch_port_primary_encap_id_not_unknown
+
+ - name: Negative assertions to check error messages
+ assert:
+ that:
+ - switch_port_no_leafs.msg == "missing required arguments{{':'}} leafs found in interface_configs"
+ - fex_vpc_no_extpaths.msg == "extpaths is required when interface_type is{{':'}} fex_vpc"
+ - fex_vpc_one_node.msg == "A interface_type of \"vpc\" requires 2 leafs"
+ - fex_vpc_one_extpaths.msg == "A interface_type of \"fex_vpc\" requires 2 extpaths"
+ - switch_port_two_leafs.msg == "The interface_types \"switch_port\", \"port_channel\", and \"fex\" do not support using multiple leafs for a single binding"
+ - switch_port_two_extpaths.msg == "The interface_types \"fex\" and \"fex_port_channel\" do not support using multiple extpaths for a single binding"
+ - fex_vpc_three_leafs.msg == "The \"leafs\" parameter must not have more than 2 entries"
+ - fex_vpc_three_expaths.msg == "The \"extpaths\" parameter must not have more than 2 entries"
+ - switch_port_encap_id_too_high.msg == "Valid VLAN assignments are from 1 to 4096"
+ - switch_port_primary_encap_id_too_high.msg == "Valid VLAN assignments are from 1 to 4096 or unknown."
+ - switch_port_primary_encap_id_not_unknown.msg.startswith("Valid VLAN assignments are from 1 to 4096 or unknown. ")
+
+ # Cleanup part
+ - name: Remove anstest tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml
new file mode 100644
index 000000000..08a62f8cc
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ap/tasks/main.yml
@@ -0,0 +1,157 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Cindy Zhao (@cizhao)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: ensure tenant exists for tests to kick off
+ cisco.aci.aci_tenant: &aci_tenant_present
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: ensure cloud ap does not exist initially
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_tenant_present
+ name: '{{ item }}'
+ state: absent
+ loop:
+ - anstest
+ - anstest2
+
+ - name: create cloud ap - check mode
+ cisco.aci.aci_cloud_ap: &aci_cloud_ap_present
+ <<: *aci_tenant_present
+ name: anstest
+ description: Ansible Test Cloud APIC
+ state: present
+ check_mode: true
+ register: cm_create_cloud_ap
+
+ - name: create cloud ap - normal mode
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_cloud_ap_present
+ register: nm_create_cloud_ap
+
+ - name: create cloud ap again - idempotency works
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_cloud_ap_present
+ register: create_cloud_ap_again
+
+ - name: create another ap - extra for query
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_cloud_ap_present
+ name: anstest2
+ register: extra_cloud_ap
+
+ - name: update cloud ap
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_cloud_ap_present
+ description: Update Ansible Test Update
+ register: update_cloud_ap
+
+ - name: verify cloud ap creation
+ assert:
+ that:
+ - cm_create_cloud_ap is changed
+ - nm_create_cloud_ap is changed
+ - cm_create_cloud_ap.previous == nm_create_cloud_ap.previous == []
+ - cm_create_cloud_ap.proposed.cloudApp.attributes.name == 'anstest'
+ - cm_create_cloud_ap.proposed.cloudApp.attributes.descr == 'Ansible Test Cloud APIC'
+ - nm_create_cloud_ap.current.0.cloudApp.attributes.annotation == 'orchestrator:ansible'
+ - nm_create_cloud_ap.current.0.cloudApp.attributes.name == 'anstest'
+ - nm_create_cloud_ap.current.0.cloudApp.attributes.descr == 'Ansible Test Cloud APIC'
+ - create_cloud_ap_again is not changed
+ - extra_cloud_ap is changed
+ - extra_cloud_ap.previous == []
+ - extra_cloud_ap.current.0.cloudApp.attributes.name == 'anstest2'
+ - extra_cloud_ap.current.0.cloudApp.attributes.descr == 'Ansible Test Cloud APIC'
+ - update_cloud_ap is changed
+ - update_cloud_ap.previous.0.cloudApp.attributes.name == 'anstest'
+ - update_cloud_ap.previous.0.cloudApp.attributes.descr == 'Ansible Test Cloud APIC'
+ - update_cloud_ap.current.0.cloudApp.attributes.name == 'anstest'
+ - update_cloud_ap.current.0.cloudApp.attributes.descr == 'Update Ansible Test Update'
+
+ - name: query all cloud ap for tenant - query tenant aps
+ cisco.aci.aci_cloud_ap: &aci_cloud_ap_query
+ <<: *aci_cloud_ap_present
+ name: "{{ fakevar | default(omit) }}"
+ state: query
+ register: query_all_tenant
+
+ - name: query all cloud ap by name
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_cloud_ap_query
+ tenant: "{{ fakevar | default(omit) }}"
+ name: anstest
+ register: query_all_ap
+
+ - name: query all cloud ap - query general
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_cloud_ap_query
+ tenant: "{{ fakevar | default(omit) }}"
+ name: "{{ fakevar | default(omit) }}"
+ register: query_all
+
+ - name: query specific cloud ap
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_cloud_ap_present
+ tenant: ansible_test
+ name: anstest
+ state: query
+ register: query_cloud_ap
+
+ - name: verify query
+ assert:
+ that:
+ - query_all_tenant is not changed
+ - query_all_tenant.current.0.fvTenant.children | length >= 2
+ - query_all_ap is not changed
+ - query_all_ap.current.0.cloudApp.attributes.name == 'anstest'
+ - query_all_ap.current.0.cloudApp.attributes.descr == 'Update Ansible Test Update'
+ - query_all is not changed
+ - query_all.current | length >= 2
+ - query_cloud_ap is not changed
+ - query_cloud_ap.current.0.cloudApp.attributes.name == 'anstest'
+ - query_cloud_ap.current.0.cloudApp.attributes.descr == 'Update Ansible Test Update'
+ - query_cloud_ap.current.0.cloudApp.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest'
+
+ - name: delete cloud ap
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_tenant_present
+ name: anstest
+ state: absent
+ register: rm_cloud_ap
+
+ - name: delete cloud ap again
+ cisco.aci.aci_cloud_ap:
+ <<: *aci_tenant_present
+ name: anstest
+ state: absent
+ register: rm_cloud_ap_again
+
+ - name: verify deletion
+ assert:
+ that:
+ - rm_cloud_ap is changed
+ - rm_cloud_ap.previous.0.cloudApp.attributes.name == 'anstest'
+ - rm_cloud_ap.current == []
+ - rm_cloud_ap_again is not changed
+ - rm_cloud_ap_again.previous == rm_cloud_ap_again.current == [] \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml
new file mode 100644
index 000000000..4679bf78d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_aws_provider/tasks/main.yml
@@ -0,0 +1,133 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Shreyas Srish (@shrsr)
+
+# 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 aws cloud site
+ when:
+ - query_cloud.current | length > 0
+ - query_cloud.current.0.cloudProvP.attributes.vendor == "aws" # This condition will execute only on cloud aws
+ block: # block specifies execution of tasks within, based on conditions
+
+ - name: Ensure tenant doesn't exist
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+
+ - name: Create tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+
+ - name: Create aws provider
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ tenant: ansible_test
+ account_id: 111111111111
+ is_trusted: true
+ state: present
+ register: aws_present
+
+ - name: Create aws provider again
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ tenant: ansible_test
+ account_id: 111111111111
+ is_trusted: true
+ state: present
+ register: aws_present_again
+
+ - name: Change to untrusted aws provider
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ tenant: ansible_test
+ account_id: 111111111111
+ is_trusted: false
+ state: present
+ register: aws_present_not_trusted
+ ignore_errors: true
+
+ - name: Delete aws provider
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+ register: aws_absent
+
+ - name: Create aws provider again after deletion as not trusted
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ tenant: ansible_test
+ account_id: 111111111111
+ is_trusted: false
+ access_key_id: 1
+ secret_access_key: 1
+ state: present
+ register: aws_present_new
+
+ - name: Create aws provider again after deletion as not trusted with account in org
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ tenant: ansible_test
+ account_id: 111111111111
+ is_trusted: false
+ access_key_id: 1
+ secret_access_key: 1
+ is_account_in_org: true
+ state: present
+ register: aws_present_add_in_org
+
+ - name: Query aws provider
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ tenant: ansible_test
+ state: query
+ register: aws_query
+
+ - name: Query all aws provider
+ cisco.aci.aci_cloud_aws_provider:
+ <<: *aci_info
+ state: query
+ register: aws_query_all
+
+ - name: Verify all
+ assert:
+ that:
+ - aws_present is changed
+ - aws_present_again is not changed
+ - aws_absent is changed
+ - aws_absent.current == []
+ - aws_present_not_trusted.msg == "APIC Error 1{{ ":" }} Invalid Configuration {{ ":" }} Untrusted tenant ansible_test has missing access or secret key"
+ - aws_present_new is changed
+ - aws_present_new.current.0.cloudAwsProvider.attributes.annotation == 'orchestrator:ansible'
+ - aws_present_new.current.0.cloudAwsProvider.attributes.accessKeyId == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
+ - aws_present_new.current.0.cloudAwsProvider.attributes.accountId == "************************************************************************************************"
+ - aws_present_new.current.0.cloudAwsProvider.attributes.dn == "uni/tn-ansible_test/awsprovider"
+ - aws_present_new.current.0.cloudAwsProvider.attributes.isAccountInOrg == "no"
+ - aws_present_add_in_org is changed
+ - aws_present_add_in_org.current.0.cloudAwsProvider.attributes.isAccountInOrg == "yes"
+ - aws_query is not changed
+ - aws_query.current.0.fvTenant.children.0.cloudAwsProvider.attributes.accessKeyId == "1"
+ - aws_query.current.0.fvTenant.children.0.cloudAwsProvider.attributes.accountId == "111111111111"
+ - aws_query.current.0.fvTenant.children.0.cloudAwsProvider.attributes.isAccountInOrg == "yes"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml
new file mode 100644
index 000000000..8d442bf14
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_bgp_asn/tasks/main.yml
@@ -0,0 +1,123 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Anvitha Jain (@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
+
+# These tasks need not be executed now, to execute the given tasks follow these steps:
+# 1. Go to cloud APIC
+# 2. Go to Region Management (top right corner blue arrow symbol)
+# 3. Deselect the box whose cloud routers option is selected
+# 4. Run the below task
+# 5. Once the tasks are completed revert the changes made in above steps.
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 cloud sites
+# when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+# block: # block specifies execution of tasks within, based on conditions
+
+# - name: Ensure cloud BGP ASN doesn't exist
+# aci_cloud_bgp_asn:
+# <<: *aci_info
+# state: absent
+
+# - name: Create cloud BGP ASN
+# aci_cloud_bgp_asn:
+# <<: *aci_info
+# state: present
+# register: asn_present
+
+# - name: Verify asn_present
+# assert:
+# that:
+# - asn_present is changed
+# - asn_present.current.0.cloudBgpAsP.attributes.asn == '0'
+
+# - name: Create cloud BGP ASN
+# aci_cloud_bgp_asn:
+# <<: *aci_info
+# annotation: 'tag_system'
+# asn: 64605
+# description: 'sample autonomous profile'
+# name: 'BGP_ASN'
+# name_alias: 'alias_sys_prof'
+# state: present
+# register: asn_present_2
+
+# - name: Verify asn_present_2
+# assert:
+# that:
+# - asn_present_2 is changed
+# - asn_present_2.current.0.cloudBgpAsP.attributes.asn == '64605'
+
+# - name: Create same cloud BGP ASN again
+# aci_cloud_bgp_asn:
+# <<: *aci_info
+# annotation: 'tag_system'
+# asn: 64605
+# description: 'sample autonomous profile'
+# name: 'BGP_ASN'
+# name_alias: 'alias_sys_prof'
+# state: present
+# register: asn_present_again
+
+# - name: Verify asn_present_again
+# assert:
+# that:
+# - asn_present_again is not changed
+# - asn_present_again.current.0.cloudBgpAsP.attributes.asn == '64605'
+
+# - name: Query particular cloud BGP ASN
+# aci_cloud_bgp_asn:
+# <<: *aci_info
+# annotation: 'tag_system'
+# asn: 64605
+# description: 'sample autonomous profile'
+# name: 'BGP_ASN'
+# name_alias: 'alias_sys_prof'
+# state: query
+# register: asn_query
+
+# # Query all will give same result as query
+# # There can be only one cloud BGP ASN
+# - name: Query all cloud BGP ASN
+# aci_cloud_bgp_asn:
+# <<: *aci_info
+# state: query
+# register: asn_query_all
+
+# - name: Verify query
+# assert:
+# that:
+# - asn_query is not changed
+# - asn_query_all is not changed
+
+# - name: Delete cloud BGP ASN
+# aci_cloud_bgp_asn:
+# <<: *aci_info
+# state: absent
+# register: asn_absent
+
+# - name: Verify absent
+# assert:
+# that:
+# - asn_absent is changed
+# - asn_absent.current == [] \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml
new file mode 100644
index 000000000..ab61eba83
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml
@@ -0,0 +1,310 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+
+ - name: Create aci cloud context profile
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ region_2 }}"
+ primary_cidr: '10.11.0.0/16'
+ cloud: "{{ cloud_type }}"
+ state: present
+ register: nm_add_aci_ctx_profile
+
+ - name: Create non_primary CIDR (check_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.0.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ check_mode: true
+ register: cm_non_primary_cidr
+
+ - name: Create non_primary CIDR (normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.0.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ register: nm_non_primary_cidr
+
+ - name: Verify cm_non_primary_cidr and nm_non_primary_cidr
+ assert:
+ that:
+ - cm_non_primary_cidr is changed
+ - nm_non_primary_cidr is changed
+ - cm_non_primary_cidr.previous == []
+ - nm_non_primary_cidr.previous == []
+ - cm_non_primary_cidr.proposed.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - cm_non_primary_cidr.proposed.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
+ - cm_non_primary_cidr.proposed.cloudCidr.attributes.primary == "no"
+ - nm_non_primary_cidr.current.0.cloudCidr.attributes.annotation == 'orchestrator:ansible'
+ - nm_non_primary_cidr.current.0.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - nm_non_primary_cidr.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
+ - nm_non_primary_cidr.current.0.cloudCidr.attributes.primary == "no"
+
+ - name: Create non_primary CIDR again
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.0.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ register: nm_non_primary_cidr_again
+
+ - name: Verify nm_non_primary_cidr_again
+ assert:
+ that:
+ - nm_non_primary_cidr_again is not changed
+ - nm_non_primary_cidr_again.previous.0.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - nm_non_primary_cidr_again.previous.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
+ - nm_non_primary_cidr_again.previous.0.cloudCidr.attributes.primary == "no"
+ - nm_non_primary_cidr_again.current.0.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - nm_non_primary_cidr_again.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
+ - nm_non_primary_cidr_again.current.0.cloudCidr.attributes.primary == "no"
+
+ - name: Change primary CIDR to non_primary (check_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.11.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ check_mode: true
+ register: cm_change_to_non_primary_cidr
+
+ - name: Change primary CIDR to non_primary (normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.11.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ ignore_errors: true
+ register: nm_change_to_non_primary_cidr
+
+ - name: Verify cm_primary_cidr and nm_change_to_non_primary_cidr
+ assert:
+ that:
+ - nm_change_to_non_primary_cidr.msg == "APIC Error 1{{':'}} Invalid Configuration {{':'}} Exactly one Primary CIDR expected for{{':'}} uni/tn-ansible_test/ctxprofile-ctx_profile_1, but found{{':'}} 0"
+ - cm_change_to_non_primary_cidr.proposed.cloudCidr.attributes.primary == "no"
+ - cm_change_to_non_primary_cidr.previous.0.cloudCidr.attributes.primary == cm_change_to_non_primary_cidr.current.0.cloudCidr.attributes.primary == "yes"
+
+ - name: Remove primary CIDR (check_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.11.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ check_mode: true
+ register: cm_remove_primary_cidr
+
+ - name: Remove primary CIDR (normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.11.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ ignore_errors: true
+ register: nm_remove_primary_cidr
+
+ - name: Verify cm_remove_primary_cidr and nm_remove_primary_cidr
+ assert:
+ that:
+ - nm_remove_primary_cidr.msg == "APIC Error 1{{':'}} Invalid Configuration {{':'}} Exactly one Primary CIDR expected for{{':'}} uni/tn-ansible_test/ctxprofile-ctx_profile_1, but found{{':'}} 0"
+ - cm_remove_primary_cidr.proposed == {}
+ - cm_remove_primary_cidr.previous.0.cloudCidr.attributes.primary == cm_remove_primary_cidr.current.0.cloudCidr.attributes.primary == "yes"
+
+ - name: Create second non_primary CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.18.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ register: nm_add_second_non_primary_cidr
+
+ - name: Verify nm_add_second_non_primary_cidr
+ assert:
+ that:
+ - nm_add_second_non_primary_cidr is changed
+ - nm_add_second_non_primary_cidr.previous == []
+ - nm_add_second_non_primary_cidr.current.0.cloudCidr.attributes.addr == "10.18.0.0/16"
+ - nm_add_second_non_primary_cidr.current.0.cloudCidr.attributes.primary == "no"
+ - nm_add_second_non_primary_cidr.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.18.0.0/16]"
+
+ - name: Change setting of second non_primary CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ cidr: 10.18.0.0/16
+ cloud_context_profile: ctx_profile_1
+ description: This is not a primary CIDR
+ name_alias: cidr_block_range
+ state: present
+ register: change_non_primary_cidr
+
+ - name: Verify change_non_primary_cidr
+ assert:
+ that:
+ - change_non_primary_cidr is changed
+ - change_non_primary_cidr.current.0.cloudCidr.attributes.addr == "10.18.0.0/16"
+ - change_non_primary_cidr.current.0.cloudCidr.attributes.descr == "This is not a primary CIDR"
+ - change_non_primary_cidr.current.0.cloudCidr.attributes.nameAlias == "cidr_block_range"
+ - change_non_primary_cidr.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.18.0.0/16]"
+
+ - name: Query all CIDRs
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: query
+ register: query_all
+
+ - name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - query_all.current.0.cloudCtxProfile.children | length == 3
+ - query_all.current.0.cloudCtxProfile.children.0.cloudCidr.attributes.addr == "10.18.0.0/16"
+ - query_all.current.0.cloudCtxProfile.children.0.cloudCidr.attributes.primary == "no"
+ - query_all.current.0.cloudCtxProfile.children.1.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - query_all.current.0.cloudCtxProfile.children.1.cloudCidr.attributes.primary == "no"
+ - query_all.current.0.cloudCtxProfile.children.2.cloudCidr.attributes.addr == "10.11.0.0/16"
+ - query_all.current.0.cloudCtxProfile.children.2.cloudCidr.attributes.primary == "yes"
+
+ - name: Query primary CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ address: 10.11.0.0/16
+ state: query
+ register: query_primary
+
+ - name: Verify query_primary
+ assert:
+ that:
+ - query_primary is not changed
+ - query_primary.current.0.cloudCidr.attributes.addr == "10.11.0.0/16"
+ - query_primary.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.11.0.0/16]"
+ - query_primary.current.0.cloudCidr.attributes.primary == "yes"
+
+ - name: Query non_primary CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ address: 10.0.0.0/16
+ state: query
+ register: query_non_primary
+
+ - name: Verify query_non_primary
+ assert:
+ that:
+ - query_non_primary is not changed
+ - query_non_primary.current.0.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - query_non_primary.current.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
+ - query_non_primary.current.0.cloudCidr.attributes.primary == "no"
+
+ - name: Query non_exsisting CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ address: non_exsisting
+ state: query
+ ignore_errors: true
+ register: query_non_existing
+
+ - name: Verify query_non_existing
+ assert:
+ that:
+ - query_non_existing.msg == "APIC Error 104{{':'}} Invalid RN cidr-[non_exsisting]"
+
+ - name: Remove non_primary CIDR(check_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.0.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ check_mode: true
+ register: cm_remove_non_primary_cidr
+
+ - name: Remove non_primary CIDR(normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: ansible_test
+ address: 10.0.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ register: nm_remove_non_primary_cidr
+
+ - name: Verify cm_remove_non_primary_cidr and nm_remove_non_primary_cidr
+ assert:
+ that:
+ - cm_remove_non_primary_cidr is changed
+ - nm_remove_non_primary_cidr is changed
+ - cm_remove_non_primary_cidr.proposed == {}
+ - nm_remove_non_primary_cidr.current == []
+ - cm_remove_non_primary_cidr.previous.0.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - cm_remove_non_primary_cidr.previous.0.cloudCidr.attributes.primary == "no"
+ - cm_remove_non_primary_cidr.previous.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
+ - nm_remove_non_primary_cidr.previous.0.cloudCidr.attributes.addr == "10.0.0.0/16"
+ - nm_remove_non_primary_cidr.previous.0.cloudCidr.attributes.primary == "no"
+ - nm_remove_non_primary_cidr.previous.0.cloudCidr.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_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_cloud_ctx_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml
new file mode 100644
index 000000000..981eadea8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml
@@ -0,0 +1,255 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+
+ - name: Verify rm_ctx_profile_1
+ assert:
+ that:
+ - rm_ctx_profile_1.current == []
+
+ - name: Ensure aci cloud context profile 2 does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_2
+ state: absent
+ register: rm_ctx_profile_2
+
+ - name: Verify rm_ctx_profile_2
+ assert:
+ that:
+ - rm_ctx_profile_2.current == []
+
+ - name: Create aci cloud context profile (check mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ region }}"
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ check_mode: true
+ register: cm_add_aci_ctx_profile
+
+ - name: Create aci cloud context profile (normal mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ region }}"
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile
+
+ - name: Verify cm_add_aci_ctx_profile
+ assert:
+ that:
+ - cm_add_aci_ctx_profile is changed
+ - cm_add_aci_ctx_profile.previous == []
+ - cm_add_aci_ctx_profile.proposed.cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - cm_add_aci_ctx_profile.proposed.cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - cm_add_aci_ctx_profile.proposed.cloudCtxProfile.children[0].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - cm_add_aci_ctx_profile.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - cm_add_aci_ctx_profile.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.primary == "yes"
+
+ - name: Verify nm_add_aci_ctx_profile
+ assert:
+ that:
+ - nm_add_aci_ctx_profile is changed
+ - nm_add_aci_ctx_profile.previous == []
+ - nm_add_aci_ctx_profile.current[0].cloudCtxProfile.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_aci_ctx_profile.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - nm_add_aci_ctx_profile.current[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - nm_add_aci_ctx_profile.current[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - nm_add_aci_ctx_profile.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - nm_add_aci_ctx_profile.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+
+ - name: Add aci cloud context profile again (check_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ region }}"
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ check_mode: true
+ register: cm_add_aci_ctx_profile_again
+
+ - name: Verify cm_add_aci_ctx_profile_again
+ assert:
+ that:
+ - cm_add_aci_ctx_profile_again is not changed
+ - cm_add_aci_ctx_profile_again.previous[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - cm_add_aci_ctx_profile_again.previous[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - cm_add_aci_ctx_profile_again.previous[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - cm_add_aci_ctx_profile_again.previous[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - cm_add_aci_ctx_profile_again.previous[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+
+
+ - name: Add aci cloud context profile again (normal_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ region }}"
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile_again
+
+ - name: Verify nm_add_aci_ctx_profile_again
+ assert:
+ that:
+ - nm_add_aci_ctx_profile_again is not changed
+ - nm_add_aci_ctx_profile_again.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - nm_add_aci_ctx_profile_again.current[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - nm_add_aci_ctx_profile_again.current[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - nm_add_aci_ctx_profile_again.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - nm_add_aci_ctx_profile_again.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+
+ - name: Add another aci cloud context profile (check_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_2
+ vrf: ctx_profile_vrf_2
+ region: "{{ region_2 }}"
+ primary_cidr: '10.101.0.0/16'
+ description: "add ctx_profile_2"
+ state: present
+ check_mode: true
+ register: cm_add_another_aci_ctx_profile
+
+ - name: Verify cm_add_another_aci_ctx_profile
+ assert:
+ that:
+ - cm_add_another_aci_ctx_profile is changed
+ - cm_add_another_aci_ctx_profile.previous == []
+ - cm_add_another_aci_ctx_profile.proposed.cloudCtxProfile.attributes.name == "ctx_profile_2"
+ - cm_add_another_aci_ctx_profile.proposed.cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_2"
+ - cm_add_another_aci_ctx_profile.proposed.cloudCtxProfile.children[0].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_2"
+ - cm_add_another_aci_ctx_profile.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.addr == "10.101.0.0/16"
+ - cm_add_another_aci_ctx_profile.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.primary == "yes"
+ - cm_add_another_aci_ctx_profile.proposed.cloudCtxProfile.attributes.descr == "add ctx_profile_2"
+
+ - name: Add another aci cloud context profile (normal_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_2
+ vrf: ctx_profile_vrf_2
+ region: "{{ region_2 }}"
+ primary_cidr: '10.101.0.0/16'
+ description: "add ctx_profile_2"
+ state: present
+ register: nm_add_another_aci_ctx_profile
+
+ - name: Verify nm_add_another_aci_ctx_profile
+ assert:
+ that:
+ - nm_add_another_aci_ctx_profile is changed
+ - nm_add_another_aci_ctx_profile.previous == []
+ - nm_add_another_aci_ctx_profile.current[0].cloudCtxProfile.attributes.name == "ctx_profile_2"
+ - nm_add_another_aci_ctx_profile.current[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_2"
+ - nm_add_another_aci_ctx_profile.current[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_2"
+ - nm_add_another_aci_ctx_profile.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.101.0.0/16"
+ - nm_add_another_aci_ctx_profile.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+ - nm_add_another_aci_ctx_profile.current[0].cloudCtxProfile.attributes.descr == "add ctx_profile_2"
+
+ - name: Query aci cloud context profile ctx_profile_1
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: query
+ register: query_aci_cloud_profile_1
+
+ - name: Verify query_aci_cloud_profile_1
+ assert:
+ that:
+ - query_aci_cloud_profile_1 is not changed
+ - query_aci_cloud_profile_1.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - query_aci_cloud_profile_1.current[0].cloudCtxProfile.children | length == 3
+
+ - name: Query all aci cloud context profiles
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ state: query
+ register: query_all
+
+ - name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current | length == 1
+ - query_all.current.0.fvTenant.children | length == 2
+
+ - name: Remove aci cloud context profile
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile
+
+ - name: Verify rm_ctx_profile
+ assert:
+ that:
+ - rm_ctx_profile.current == []
+ - rm_ctx_profile.previous.0.cloudCtxProfile.attributes.name == "ctx_profile_1"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml
new file mode 100644
index 000000000..966b6afc2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg/tasks/main.yml
@@ -0,0 +1,185 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Cindy Zhao (@cizhao)
+
+# 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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure tenant exists
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure application profile exists
+ cisco.aci.aci_cloud_ap: &aci_cloud_ap_present
+ <<: *aci_tenant_present
+ name: anstest
+ description: Ansible Test Cloud APIC
+ state: present
+ register: create_cloud_ap
+
+ - name: Ensure vrf exist
+ cisco.aci.aci_vrf: &aci_vrf_present
+ <<: *aci_tenant_present
+ vrf: anstest
+ description: Ansible Test
+ register: vrf_present
+
+ - name: Create another vrf
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ vrf: anstest_2
+ register: another_vrf_present
+
+ - name: Create aci cloud epg (check_mode)
+ cisco.aci.aci_cloud_epg: &aci_cloud_epg_present
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ vrf: anstest
+ description: Aci Cloud EPG
+ name: anstest
+ state: present
+ check_mode: true
+ register: cm_epg_present
+
+ - name: Create aci cloud epg (normal mode)
+ cisco.aci.aci_cloud_epg:
+ <<: *aci_cloud_epg_present
+ register: nm_epg_present
+
+ - name: Create aci cloud epg again
+ cisco.aci.aci_cloud_epg:
+ <<: *aci_cloud_epg_present
+ register: nm_epg_present_again
+
+ - name: Create another cloud epg
+ cisco.aci.aci_cloud_epg:
+ <<: *aci_cloud_epg_present
+ name: ansible_cloud_epg
+ register: nm_another_epg_present
+
+ - name: Verify cloud epg creation
+ assert:
+ that:
+ - cm_epg_present is changed
+ - nm_epg_present is changed
+ - nm_epg_present_again is not changed
+ - cm_epg_present.previous == nm_epg_present.previous == []
+ - cm_epg_present.proposed.cloudEPg.attributes.name == 'anstest'
+ - cm_epg_present.proposed.cloudEPg.attributes.descr == 'Aci Cloud EPG'
+ - cm_epg_present.proposed.cloudEPg.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudepg-anstest'
+ - cm_epg_present.proposed.cloudEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest'
+ - nm_epg_present.current.0.cloudEPg.attributes.annotation == 'orchestrator:ansible'
+ - nm_epg_present.current.0.cloudEPg.attributes.name == 'anstest'
+ - nm_epg_present.current.0.cloudEPg.attributes.descr == 'Aci Cloud EPG'
+ - nm_epg_present.current.0.cloudEPg.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudepg-anstest'
+ - nm_epg_present.current.0.cloudEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest'
+ - nm_epg_present_again.previous == nm_epg_present_again.current
+ - nm_another_epg_present is changed
+ - nm_another_epg_present.previous == []
+ - nm_another_epg_present.current.0.cloudEPg.attributes.name == 'ansible_cloud_epg'
+
+ - name: Update cloud epg with another vrf
+ cisco.aci.aci_cloud_epg:
+ <<: *aci_cloud_epg_present
+ vrf: anstest_2
+ register: update_cloud_epg
+
+ - name: Update cloud epg without vrf
+ cisco.aci.aci_cloud_epg:
+ <<: *aci_cloud_epg_present
+ vrf: "{{ fakevar | default(omit) }}"
+ register: no_vrf
+
+ # - name: Create cloud epg without vrf
+ # cisco.aci.aci_cloud_epg:
+ # <<: *aci_cloud_epg_present
+ # name: epg_without_vrf
+ # vrf: "{{ fakevar | default(omit) }}"
+ # register: create_no_vrf
+
+ - name: Veirfy update_cloud_epg
+ assert:
+ that:
+ - update_cloud_epg is changed
+ - update_cloud_epg.current.0.cloudEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest_2'
+
+ - name: Query specific cloud epg
+ cisco.aci.aci_cloud_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ name: anstest
+ state: query
+ register: cloud_epg_query
+
+ - name: query all
+ cisco.aci.aci_cloud_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ state: query
+ register: query_all
+
+ - name: Verify query
+ assert:
+ that:
+ - cloud_epg_query is not changed
+ - cloud_epg_query.current.0.cloudEPg.attributes.name == 'anstest'
+ - cloud_epg_query.current.0.cloudEPg.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudepg-anstest'
+ - cloud_epg_query.current.0.cloudEPg.attributes.descr == 'Aci Cloud EPG'
+ - cloud_epg_query.current.0.cloudEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest_2'
+ - cloud_epg_query.current.0.cloudEPg.children.0.cloudRsCloudEPgCtx.attributes.tDn == 'uni/tn-ansible_test/ctx-anstest_2'
+ - query_all is not changed
+ - query_all.current.0.cloudApp.children | length >= 2
+
+ - name: Remove cloud epg
+ cisco.aci.aci_cloud_epg: &cloud_epg_absent
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ name: anstest
+ state: absent
+ register: cloud_epg_absent
+
+ - name: Remove cloud epg again
+ cisco.aci.aci_cloud_epg:
+ <<: *cloud_epg_absent
+ register: cloud_epg_absent_again
+
+ - name: Verify deletion
+ assert:
+ that:
+ - cloud_epg_absent is changed
+ - cloud_epg_absent.current == []
+ - cloud_epg_absent_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_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_cloud_epg_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml
new file mode 100644
index 000000000..c1261eae7
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_epg_selector/tasks/main.yml
@@ -0,0 +1,232 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Cindy Zhao (@cizhao)
+
+# 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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure tenant exists
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure application profile exists
+ cisco.aci.aci_cloud_ap: &aci_cloud_ap_present
+ <<: *aci_tenant_present
+ name: anstest
+ description: Ansible Test Cloud APIC
+ state: present
+ register: create_cloud_ap
+
+ - name: Ensure vrf exist
+ cisco.aci.aci_vrf: &aci_vrf_present
+ <<: *aci_tenant_present
+ vrf: anstest
+ description: Ansible Test
+ register: vrf_present
+
+ - name: Create aci cloud epg
+ cisco.aci.aci_cloud_epg: &aci_cloud_epg_present
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ vrf: anstest
+ description: Aci Cloud EPG
+ name: anstest
+ state: present
+ register: nm_epg_present
+
+ - name: Create aci cloud epg selector (check_mode)
+ cisco.aci.aci_cloud_epg_selector: &aci_cloud_epg_selector
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ epg: anstest
+ description: cloud epg selector
+ name: ansible_selector
+ expressions:
+ - key: ip
+ operator: in
+ value: 10.10.10.1
+ state: present
+ check_mode: true
+ register: cm_selector_present
+
+ - name: Create aci cloud epg selector (normal mode)
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_cloud_epg_selector
+ register: nm_selector_present
+
+ - name: Create aci cloud epg again
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_cloud_epg_selector
+ register: selector_present_again
+
+ - name: Verify creation of cloud epg selector
+ assert:
+ that:
+ - cm_selector_present is changed
+ - nm_selector_present is changed
+ - selector_present_again is not changed
+ - cm_selector_present.previous == nm_selector_present.previous == []
+ - cm_selector_present.proposed.cloudEPSelector.attributes.descr == 'cloud epg selector'
+ - cm_selector_present.proposed.cloudEPSelector.attributes.matchExpression == "IP in('10.10.10.1')"
+ - cm_selector_present.proposed.cloudEPSelector.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudepg-anstest/epselector-ansible_selector'
+ - cm_selector_present.proposed.cloudEPSelector.attributes.name == 'ansible_selector'
+ - nm_selector_present.current.0.cloudEPSelector.attributes.annotation == 'orchestrator:ansible'
+ - nm_selector_present.current.0.cloudEPSelector.attributes.descr == 'cloud epg selector'
+ - nm_selector_present.current.0.cloudEPSelector.attributes.matchExpression == "IP in('10.10.10.1')"
+ - nm_selector_present.current.0.cloudEPSelector.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudepg-anstest/epselector-ansible_selector'
+ - nm_selector_present.current.0.cloudEPSelector.attributes.name == 'ansible_selector'
+ - selector_present_again is not changed
+ - selector_present_again.previous == selector_present_again.current == nm_selector_present.current
+
+ - name: Update aci cloud epg selector
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_cloud_epg_selector
+ expressions:
+ - key: ip
+ operator: in
+ value: 10.10.10.1,10.10.10.2
+ - key: region
+ operator: equals
+ value: '{{ region }}'
+ - key: test_expression
+ operator: does_not_have_key
+ register: udpate_selector
+
+ - name: Create second aci cloud epg selector
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_cloud_epg_selector
+ description: second cloud epg selector
+ name: ansible_selector_2
+ expressions:
+ - key: ip
+ operator: not_equals
+ value: 10.10.10.3
+ - key: region
+ operator: not_in
+ value: '{{ region_2 }}'
+ - key: test_expression_2
+ operator: has_key
+ - key: zone
+ operator: does_not_have_key
+ register: sec_selector
+
+ - name: Create selector with incorrect parameter - has_key with ip
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_cloud_epg_selector
+ name: ip_has_key
+ expressions:
+ - key: ip
+ operator: has_key
+ ignore_errors: true
+ register: ip_has_key
+
+ - name: Create selector with incorrect parameter - does_not_have_key with value
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_cloud_epg_selector
+ name: does_not_have_key
+ expressions:
+ - key: ctm_test
+ operator: does_not_have_key
+ value: test_value
+ ignore_errors: true
+ register: does_not_without_key
+
+ - name: Create selector with incorrect parameter - without value
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_cloud_epg_selector
+ name: equals_without_value
+ expressions:
+ - key: ctm_test
+ operator: equals
+ ignore_errors: true
+ register: equals_without_value
+
+ - name: Verify creation of other selectors
+ assert:
+ that:
+ - sec_selector is changed
+ - udpate_selector is changed
+ - sec_selector.current.0.cloudEPSelector.attributes.name == 'ansible_selector_2'
+ - sec_selector.current.0.cloudEPSelector.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudepg-anstest/epselector-ansible_selector_2'
+ - ip_has_key.msg == "Operator 'has_key' is not supported when expression key is 'ip'"
+ - equals_without_value.msg == "Attribute 'value' needed for operator 'equals' in expression 'ctm_test'"
+ - does_not_without_key.msg == "Attribute 'value' is not supported for operator 'does_not_have_key' in expression 'ctm_test'"
+
+ - name: Query specific cloud epg selector
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ epg: anstest
+ name: ansible_selector
+ state: query
+ register: query_selector
+
+ - name: Query all cloud epg selectors
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ epg: anstest
+ state: query
+ register: query_all
+
+ - name: Verify query
+ assert:
+ that:
+ - query_selector.current.0.cloudEPSelector.attributes.name == 'ansible_selector'
+ - query_all.current.0.cloudEPg.children | length >= 2
+
+ - name: Remove cloud epg selector
+ cisco.aci.aci_cloud_epg_selector: &selector_absent
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ epg: anstest
+ name: ansible_selector_2
+ state: absent
+ register: rm_selector_2
+
+ - name: Remove cloud epg selector again
+ cisco.aci.aci_cloud_epg_selector:
+ <<: *selector_absent
+ register: rm_selector_2_again
+
+ - name: Verify rm_selector_2
+ assert:
+ that:
+ - rm_selector_2 is changed
+ - rm_selector_2.current == []
+ - rm_selector_2_again is not changed \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml
new file mode 100644
index 000000000..b9511e98f
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg/tasks/main.yml
@@ -0,0 +1,191 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Anvitha Jain (@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: '{{ 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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure cloud external epg doesn't exist
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ name: anstest
+ state: absent
+
+ - name: Ensure tenant exists
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure application profile exists
+ cisco.aci.aci_cloud_ap: &aci_cloud_ap_present
+ <<: *aci_tenant_present
+ name: anstest
+ description: Ansible Test Cloud APIC
+ state: present
+ register: create_cloud_ap
+
+ - name: Ensure vrf exist
+ cisco.aci.aci_vrf: &aci_vrf_present
+ <<: *aci_tenant_present
+ vrf: anstest
+ description: Ansible Test
+ register: vrf_present
+
+ - name: Create another vrf
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ vrf: anstest_2
+ register: another_vrf_present
+
+ - name: Create aci cloud external epg (check_mode)
+ cisco.aci.aci_cloud_external_epg: &aci_cloud_ext_epg_present
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ vrf: anstest
+ description: Aci Cloud External EPG
+ name: anstest
+ route_reachability: internet
+ state: present
+ check_mode: true
+ register: cm_epg_present
+
+ - name: Create aci cloud external epg (normal mode)
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_cloud_ext_epg_present
+ register: nm_epg_present
+
+ - name: Create aci cloud external epg again
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_cloud_ext_epg_present
+ register: nm_epg_present_again
+
+ - name: Verify cloud external epg creation
+ assert:
+ that:
+ - cm_epg_present is changed
+ - nm_epg_present is changed
+ - nm_epg_present_again is not changed
+ - cm_epg_present.previous == nm_epg_present.previous == []
+ - cm_epg_present.proposed.cloudExtEPg.attributes.name == 'anstest'
+ - cm_epg_present.proposed.cloudExtEPg.attributes.descr == 'Aci Cloud External EPG'
+ - cm_epg_present.proposed.cloudExtEPg.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudextepg-anstest'
+ - cm_epg_present.proposed.cloudExtEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest'
+ - nm_epg_present.current.0.cloudExtEPg.attributes.annotation == 'orchestrator:ansible'
+ - nm_epg_present.current.0.cloudExtEPg.attributes.name == 'anstest'
+ - nm_epg_present.current.0.cloudExtEPg.attributes.descr == 'Aci Cloud External EPG'
+ - nm_epg_present.current.0.cloudExtEPg.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudextepg-anstest'
+ - nm_epg_present.current.0.cloudExtEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest'
+ - nm_epg_present_again.previous == nm_epg_present_again.current
+
+ - name: Create another cloud external epg
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_cloud_ext_epg_present
+ name: ansible_cloud_ext_epg
+ register: nm_another_epg_present
+
+ - name: Verify another cloud external epg creation
+ assert:
+ that:
+ - nm_another_epg_present is changed
+ - nm_another_epg_present.previous == []
+ - nm_another_epg_present.current.0.cloudExtEPg.attributes.name == 'ansible_cloud_ext_epg'
+
+ - name: Update cloud external epg with another vrf
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_cloud_ext_epg_present
+ vrf: anstest_2
+ register: update_cloud_ext_epg
+
+ - name: Update cloud external epg without vrf
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_cloud_ext_epg_present
+ vrf: "{{ fakevar | default(omit) }}"
+ register: no_vrf
+
+ - name: Veirfy update_cloud_ext_epg
+ assert:
+ that:
+ - update_cloud_ext_epg is changed
+ - update_cloud_ext_epg.current.0.cloudExtEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest_2'
+
+ - name: Query specific cloud external epg
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ name: anstest
+ state: query
+ register: cloud_ext_epg_query
+
+ - name: query all
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ state: query
+ register: query_all
+
+ - name: Verify query
+ assert:
+ that:
+ - cloud_ext_epg_query is not changed
+ - cloud_ext_epg_query.current.0.cloudExtEPg.attributes.name == 'anstest'
+ - cloud_ext_epg_query.current.0.cloudExtEPg.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudextepg-anstest'
+ - cloud_ext_epg_query.current.0.cloudExtEPg.attributes.descr == 'Aci Cloud External EPG'
+ - cloud_ext_epg_query.current.0.cloudExtEPg.children.0.cloudRsCloudEPgCtx.attributes.tnFvCtxName == 'anstest_2'
+ - cloud_ext_epg_query.current.0.cloudExtEPg.children.0.cloudRsCloudEPgCtx.attributes.tDn == 'uni/tn-ansible_test/ctx-anstest_2'
+ - query_all is not changed
+ - query_all.current.0.cloudApp.children | length >= 2
+
+ - name: Remove cloud external epg
+ cisco.aci.aci_cloud_external_epg: &cloud_ext_epg_absent
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ name: anstest
+ state: absent
+ register: cloud_ext_epg_absent
+
+ - name: Remove cloud external epg again
+ cisco.aci.aci_cloud_external_epg:
+ <<: *cloud_ext_epg_absent
+ register: cloud_ext_epg_absent_again
+
+ - name: Verify deletion
+ assert:
+ that:
+ - cloud_ext_epg_absent is changed
+ - cloud_ext_epg_absent.current == []
+ - cloud_ext_epg_absent_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_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_cloud_external_epg_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml
new file mode 100644
index 000000000..21260c054
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_external_epg_selector/tasks/main.yml
@@ -0,0 +1,182 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Anvitha Jain (@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: '{{ 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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure cloud external epg doesn't exist
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ name: anstest
+ state: absent
+
+ - name: Ensure tenant exists
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure application profile exists
+ cisco.aci.aci_cloud_ap: &aci_cloud_ap_present
+ <<: *aci_tenant_present
+ name: anstest
+ description: Ansible Test Cloud APIC
+ state: present
+ register: create_cloud_ap
+
+ - name: Ensure vrf exist
+ cisco.aci.aci_vrf: &aci_vrf_present
+ <<: *aci_tenant_present
+ vrf: anstest
+ description: Ansible Test
+ register: vrf_present
+
+ - name: Create another vrf
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ vrf: anstest_2
+ register: another_vrf_present
+
+ - name: Ensure aci cloud external epg exist
+ cisco.aci.aci_cloud_external_epg:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ vrf: anstest
+ description: Aci Cloud External EPG
+ name: anstest
+ route_reachability: internet
+ state: present
+ register: ext_epg_present
+
+ - name: Create aci cloud external epg selector (check_mode)
+ cisco.aci.aci_cloud_external_epg_selector: &aci_cloud_ext_epg_present
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ cloud_external_epg: anstest
+ name: subnet1
+ subnet: 10.0.0.0/16
+ state: present
+ check_mode: true
+ register: cm_epg_present
+
+ - name: Create aci cloud external epg selector (normal mode)
+ cisco.aci.aci_cloud_external_epg_selector:
+ <<: *aci_cloud_ext_epg_present
+ register: nm_epg_present
+
+ - name: Create aci cloud external epg selector again
+ cisco.aci.aci_cloud_external_epg_selector:
+ <<: *aci_cloud_ext_epg_present
+ register: nm_epg_present_again
+
+ - name: Verify cloud external epg creation
+ assert:
+ that:
+ - cm_epg_present is changed
+ - nm_epg_present is changed
+ - nm_epg_present_again is not changed
+ - cm_epg_present.previous == nm_epg_present.previous == []
+ - cm_epg_present.proposed.cloudExtEPSelector.attributes.name == 'subnet1'
+ - cm_epg_present.proposed.cloudExtEPSelector.attributes.subnet == '10.0.0.0/16'
+ - cm_epg_present.proposed.cloudExtEPSelector.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudextepg-anstest/extepselector-[10.0.0.0/16]'
+ - nm_epg_present.current.0.cloudExtEPSelector.attributes.annotation == 'orchestrator:ansible'
+ - nm_epg_present.current.0.cloudExtEPSelector.attributes.name == 'subnet1'
+ - nm_epg_present.proposed.cloudExtEPSelector.attributes.subnet == '10.0.0.0/16'
+ - nm_epg_present.current.0.cloudExtEPSelector.attributes.dn == 'uni/tn-ansible_test/cloudapp-anstest/cloudextepg-anstest/extepselector-[10.0.0.0/16]'
+ - nm_epg_present_again.previous == nm_epg_present_again.current
+
+ - name: Create another cloud external epg
+ cisco.aci.aci_cloud_external_epg_selector:
+ <<: *aci_cloud_ext_epg_present
+ name: subnet2
+ subnet: 10.10.10.10/24
+ register: nm_another_epg_present
+
+ - name: Verify another cloud external epg creation
+ assert:
+ that:
+ - nm_another_epg_present is changed
+ - nm_another_epg_present.previous == []
+ - nm_another_epg_present.current.0.cloudExtEPSelector.attributes.name == 'subnet2'
+ - nm_another_epg_present.current.0.cloudExtEPSelector.attributes.subnet == '10.10.10.10/24'
+
+ - name: Query specific cloud external epg selector
+ cisco.aci.aci_cloud_external_epg_selector:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ cloud_external_epg: anstest
+ name: subnet1
+ state: query
+ register: cloud_ext_epg_query
+
+ - name: query all selectors
+ cisco.aci.aci_cloud_external_epg_selector:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ cloud_external_epg: anstest
+ state: query
+ register: query_all
+
+ - name: Verify query
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.cloudExtEPg.children | length >= 2
+
+ - name: Remove cloud external epg selector
+ cisco.aci.aci_cloud_external_epg_selector: &cloud_ext_epg_absent
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ cloud_external_epg: anstest
+ name: subnet1
+ subnet: 10.0.0.0/16
+ state: absent
+ register: cloud_ext_epg_absent
+
+ - name: Remove cloud external epg again
+ cisco.aci.aci_cloud_external_epg_selector:
+ <<: *cloud_ext_epg_absent
+ register: cloud_ext_epg_absent_again
+
+ - name: Verify deletion
+ assert:
+ that:
+ - cloud_ext_epg_absent is changed
+ - cloud_ext_epg_absent.current == []
+ - cloud_ext_epg_absent_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml
new file mode 100644
index 000000000..9cc4c87b7
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml
@@ -0,0 +1,56 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Lionel Hercot (@lhercot) <lhercot@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+- name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+# QUERY OBJECTS
+- name: Query cloud provider object
+ aci_cloud_provider:
+ <<: *aci_info
+ state: query
+ register: query_cloud
+ when: version.current.0.topSystem.attributes.version is version('4.1', '>=')
+
+- name: Set vars
+ set_fact:
+ query_cloud:
+ current: []
+ when: version.current.0.topSystem.attributes.version is version('4.1', '<')
+
+- name: Verify query_cloud for all sites
+ assert:
+ that:
+ - query_cloud is not changed
+
+- name: Verify query_cloud for Cloud Sites
+ assert:
+ that:
+ - query_cloud is not changed
+ - query_cloud.current.0.cloudProvP.attributes.environment == "public-cloud"
+ - '"vendor" in query_cloud.current.0.cloudProvP.attributes'
+ when:
+ - query_cloud.current | length > 0 # This condition will execute only cloud sites
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml
new file mode 100644
index 000000000..f4c19c3f7
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml
@@ -0,0 +1,74 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Query all regions
+ aci_cloud_region:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ state: query
+ register: query_all
+
+ - name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.cloudProvP.attributes.dn == "uni/clouddomp/provp-{{cloud_type}}"
+ - query_all.current.0.cloudProvP.attributes.vendor == "{{cloud_type}}"
+ - query_all.current.0.cloudProvP.children | length > 10
+ when: query_all.current != []
+
+ - name: Query a specific region
+ aci_cloud_region:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ region: "{{ region_2 }}"
+ state: query
+ register: query_region
+
+ - name: Verify query_region
+ assert:
+ that:
+ - query_region is not changed
+ - query_region.current.0.cloudRegion.attributes.adminSt == "managed"
+ - query_region.current.0.cloudRegion.attributes.dn == "uni/clouddomp/provp-{{cloud_type}}/region-{{region_2}}"
+ - query_region.current.0.cloudRegion.attributes.name == "{{region_2}}"
+ when: query_region.current != []
+
+ - name: Query non_existing region
+ aci_cloud_region:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ region: non_existing
+ state: query
+ register: query_non_existing_region
+
+ - name: Verify query_non_existing_region
+ assert:
+ that:
+ - query_non_existing_region is not changed
+ - query_non_existing_region.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_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_cloud_subnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml
new file mode 100644
index 000000000..e438b4144
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml
@@ -0,0 +1,261 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+
+ - name: Verify rm_ctx_profile_1
+ assert:
+ that:
+ - rm_ctx_profile_1.current == []
+
+ - name: Create aci cloud context profile (normal mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ region_2 }}"
+ primary_cidr: '10.50.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile
+
+ - name: Create aci cloud subnet (check_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ availability_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: test description
+ check_mode: true
+ register: cm_add_subnet
+
+ - name: Create aci cloud subnet (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ availability_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: test description
+ register: nm_add_subnet
+
+ - name: Verify cm_add_subnet
+ assert:
+ that:
+ - cm_add_subnet is changed
+ - cm_add_subnet.previous == []
+ - cm_add_subnet.proposed.cloudSubnet.attributes.ip == "10.50.0.1"
+ - cm_add_subnet.proposed.cloudSubnet.attributes.descr == "test description"
+ - cm_add_subnet.proposed.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]"
+
+ - name: Create aci cloud subnet again (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ availability_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: test description
+ register: nm_add_subnet_again
+
+ - name: Verify nm_add_subnet_again
+ assert:
+ that:
+ - nm_add_subnet_again is not changed
+
+ - name: Create another cloud subnet (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ availability_zone | default(omit) }}"
+ address: 10.50.0.2
+ description: another subnet
+ register: nm_add_another_subnet
+
+ - name: Verify nm_add_another_subnet
+ assert:
+ that:
+ - nm_add_another_subnet is changed
+ - nm_add_another_subnet.previous == []
+ - nm_add_another_subnet.current.0.cloudSubnet.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_another_subnet.current.0.cloudSubnet.attributes.descr == "another subnet"
+ - nm_add_another_subnet.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.2]"
+
+ - name: Create cloud subnet 3(normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ availability_zone | default(omit) }}"
+ address: 10.50.0.3
+ name: subnet_3
+ register: nm_add_subnet_3
+
+ - name: Specify subnet as VpnGateway enabled
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ availability_zone | default(omit) }}"
+ address: 10.50.0.1
+ # name: subnet_1
+ description: change subnet 1
+ vnet_gateway: "{{ vnet_gateway | default(omit)}}"
+ #scope: public
+ register: nm_change_subnet_1
+
+ # Enable vpn_gateway router in cloud ctx profile
+ - name: Enable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: present
+
+ # Try to disable vpn_gateway router again in cloud ctx profile
+ - name: Disable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: absent
+
+ - name: Query all subnets
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ state: query
+ register: query_all
+
+ - name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.cloudCidr.attributes.addr == "10.50.0.0/16"
+ - query_all.current.0.cloudCidr.children | length == 3
+
+ - name: Query a specific subnet
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ address: 10.50.0.1
+ state: query
+ register: query_subnet_1
+
+ - name: Verify query_subnet_1
+ assert:
+ that:
+ - query_subnet_1 is not changed
+ - query_subnet_1.current.0.cloudSubnet.attributes.ip == "10.50.0.1"
+ - query_subnet_1.current.0.cloudSubnet.attributes.scope == "private"
+ - query_subnet_1.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]"
+
+ - name: Remove subnet 3 (check_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ address: 10.50.0.3
+ state: absent
+ check_mode: true
+ register: cm_remove_subnet_3
+
+ - name: Verify cm_remove_subnet_3
+ assert:
+ that:
+ - cm_remove_subnet_3 is changed
+ - cm_remove_subnet_3.proposed == {}
+ - cm_remove_subnet_3.previous.0.cloudSubnet.attributes.ip == "10.50.0.3"
+
+ - name: Remove subnet 3 (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ address: 10.50.0.3
+ state: absent
+ register: nm_remove_subnet_3
+
+ - name: Verify nm_remove_subnet_3
+ assert:
+ that:
+ - nm_remove_subnet_3 is changed
+ - nm_remove_subnet_3.current == []
+ - nm_remove_subnet_3.previous.0.cloudSubnet.attributes.ip == "10.50.0.3"
+
+ - name: Remove subnet 3 again
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ address: 10.50.0.3
+ state: absent
+ register: nm_remove_subnet_3_again
+
+ - name: Verify nm_remove_subnet_3_again
+ assert:
+ that:
+ - nm_remove_subnet_3_again is not changed
+ - nm_remove_subnet_3_again.previous == []
+ - nm_remove_subnet_3_again.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml
new file mode 100644
index 000000000..834331a03
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml
@@ -0,0 +1,114 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+ - name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+
+ - name: Verify rm_ctx_profile_1
+ assert:
+ that:
+ - rm_ctx_profile_1.current == []
+
+ - name: Create aci cloud context profile (normal mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud: "{{ cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ region_2 }}"
+ primary_cidr: '10.50.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile
+
+ - name: Create aci cloud subnet with VpnGateway enabled (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ availability_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: specify this subnet as VpnGateway router
+ vnet_gateway: "{{ vnet_gateway | default(omit)}}"
+ state: present
+ register: nm_add_subnet
+
+ - name: Enable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: present
+
+ - name: Disable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: absent
+
+ - name: Enable VpnGateway again
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: present
+
+ - name: Query VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ register: query_vpn_gateway
+
+ - name: Verify VpnGateway
+ assert:
+ that:
+ - query_vpn_gateway is not changed
+ - query_vpn_gateway.current.0.cloudRouterP.children | length == 3
+ - query_vpn_gateway.current.0.cloudRouterP.attributes.annotation == 'orchestrator:ansible'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml
new file mode 100644
index 000000000..85a2ec087
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml
@@ -0,0 +1,97 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Query all zones under us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ region: "{{ region_2 }}"
+ state: query
+ register: query_all
+
+ - name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.cloudRegion.attributes.name == "{{region_2}}"
+ - query_all.current.0.cloudRegion.children | length >= 1
+
+ - name: Query a specific zone under region us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ region: "{{ region_2 }}"
+ zone: "{{ availability_zone | default(omit) }}"
+ state: query
+ register: query_zone_1
+
+ - name: Query another specific zone under region us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ region: "{{ region_2 }}"
+ zone: us-west-1b
+ state: query
+ register: query_zone_2
+
+ - name: Verify query_zone_1 and query_zone_2
+ assert:
+ that:
+ - query_zone_1 is not changed
+ - query_zone_2 is not changed
+ - query_zone_1.current.0.cloudZone.attributes.name == "{{availability_zone}}"
+ - query_zone_1.current.0.cloudZone.attributes.dn == "uni/clouddomp/provp-{{cloud_type}}/region-{{region_2}}/zone-us-west-1a"
+ - query_zone_2.current.0.cloudZone.attributes.name == "us-west-1b"
+ - query_zone_2.current.0.cloudZone.attributes.dn == "uni/clouddomp/provp-{{cloud_type}}/region-{{region_2}}/zone-us-west-1b"
+ when: query_zone_1.current != [] and query_zone_2.current != []
+
+ - name: Query non_existing zone under region us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ region: "{{ region_2 }}"
+ zone: non_existing
+ state: query
+ register: query_non_existing_zone
+
+ - name: Query zone under non_existing region
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: "{{ cloud_type }}"
+ region: non_existing
+ zone: "{{ availability_zone | default(omit) }}"
+ state: query
+ register: query_non_existing_region
+
+ - name: Verify query_non_existing_zone
+ assert:
+ that:
+ - query_non_existing_zone is not changed
+ - query_non_existing_zone.current == []
+ - query_non_existing_region is not changed
+ - query_non_existing_region.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_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_config_export_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/tasks/main.yml
new file mode 100644
index 000000000..bb290aa5f
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_export_policy/tasks/main.yml
@@ -0,0 +1,161 @@
+# Author: Tim Cragg (@timcragg)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_export_policy
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ name: ansible_export_policy
+ state: absent
+
+- name: Delete Config Export Policy with scheduler
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ name: ansible_export_policy_scheduler
+ state: absent
+
+- name: Delete Config Export Policy with export destination
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ name: ansible_export_policy_destination
+ state: absent
+
+# CREATE CONFIG EXPORT POLICY
+- name: Create a Config Export Policy (check mode)
+ cisco.aci.aci_config_export_policy: &aci_conf_policy
+ <<: *aci_info
+ name: ansible_export_policy
+ description: Test Config Export Policy
+ scheduler: test_scheduler
+ export_destination: test_dest
+ start_now: no
+ check_mode: yes
+ register: cm_create_conf_export
+
+- name: Create a Config Export Policy
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_conf_policy
+ register: nm_create_conf_export
+
+- name: Create a Config Export Policy again
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_conf_policy
+ register: nm_create_conf_export_again
+
+- name: Create a Config Export Policy with scheduler, set to start_now
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ name: ansible_export_policy_scheduler
+ scheduler: test_scheduler
+ start_now: yes
+ register: sched_policy
+
+- name: Create a Config Export Policy with export destination
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ name: ansible_export_policy_destination
+ export_destination: test_dest
+ register: dest_policy
+
+- name: Verify creation of File Remote Path
+ ansible.builtin.assert:
+ that:
+ - cm_create_conf_export is changed
+ - nm_create_conf_export is changed
+ - nm_create_conf_export_again is not changed
+ - nm_create_conf_export.current.0.configExportP.attributes.name == "ansible_export_policy"
+ - nm_create_conf_export.current.0.configExportP.attributes.descr == "Test Config Export Policy"
+ - nm_create_conf_export.current.0.configExportP.attributes.format == "json"
+ - nm_create_conf_export.current.0.configExportP.attributes.adminSt == "untriggered"
+ - nm_create_conf_export_again.current.0.configExportP.attributes.name == "ansible_export_policy"
+ - nm_create_conf_export_again.current.0.configExportP.attributes.descr == "Test Config Export Policy"
+ - nm_create_conf_export_again.current.0.configExportP.attributes.format == "json"
+ - nm_create_conf_export_again.current.0.configExportP.attributes.adminSt == "untriggered"
+ - sched_policy.current.0.configExportP.children.1.configRsExportScheduler.attributes.tnTrigSchedPName == "test_scheduler"
+ - sched_policy.sent.configExportP.attributes.adminSt == "triggered"
+ - dest_policy.current.0.configExportP.children.0.configRsRemotePath.attributes.tnFileRemotePathName == "test_dest"
+
+# UPDATE CONFIG EXPORT POLICY
+- name: Update Config Export Policy
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_conf_policy
+ format: xml
+ target_dn: uni/tn-common
+ register: update_conf_export
+
+- name: Verify update of File Remote Path
+ ansible.builtin.assert:
+ that:
+ - update_conf_export is changed
+ - update_conf_export.current.0.configExportP.attributes.name == "ansible_export_policy"
+ - update_conf_export.current.0.configExportP.attributes.descr == "Test Config Export Policy"
+ - update_conf_export.current.0.configExportP.attributes.format == "xml"
+ - update_conf_export.current.0.configExportP.attributes.targetDn == "uni/tn-common"
+
+# QUERY CONFIG EXPORT POLICY
+- name: Query Config Export Policy
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_conf_policy
+ state: query
+ register: query_one
+
+- name: Query all Config Export Policies
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify Config Export Policy queries
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current.0.configExportP.attributes.name == "ansible_export_policy"
+ - query_one.current.0.configExportP.attributes.descr == "Test Config Export Policy"
+ - query_one.current.0.configExportP.attributes.format == "xml"
+ - query_one.current.0.configExportP.attributes.targetDn == "uni/tn-common"
+ - query_all is not changed
+ - query_all.current | length > 1
+
+# REMOVE CONFIG EXPORT POLICY
+- name: Delete a Config Export Policy
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_conf_policy
+ state: absent
+ register: delete
+
+- name: Delete File Config Export Policy again
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_conf_policy
+ state: absent
+ register: delete_again
+
+- name: Verify deletion of Config Export Policy
+ ansible.builtin.assert:
+ that:
+ - delete is changed
+ - delete_again is not changed
+ - delete.current == []
+
+- name: Delete Config Export Policy with scheduler
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ name: ansible_export_policy_scheduler
+ state: absent
+
+- name: Delete Config Export Policy with export destination
+ cisco.aci.aci_config_export_policy:
+ <<: *aci_info
+ name: ansible_export_policy_destination
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..df4c64069
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml
@@ -0,0 +1,110 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: ensure tenant does not exist for tests to kick off
+ cisco.aci.aci_tenant: &aci_tenant_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
+ state: absent
+ tenant: ansible_test
+
+- name: create a snapshot
+ cisco.aci.aci_config_snapshot: &create_snapshot
+ <<: *aci_tenant_absent
+ state: present
+ tenant: "{{ fakevar | default(omit) }}"
+ export_policy: anstest
+
+- name: create a tenant - use for rollback
+ cisco.aci.aci_tenant: &aci_tenant
+ <<: *create_snapshot
+ export_policy: "{{ fakevar | default(omit) }}"
+ tenant: ansible_test
+ register: tenant_present
+
+- name: create a new snapshot
+ cisco.aci.aci_config_snapshot:
+ <<: *create_snapshot
+ register: create_snapshot_annotation_check
+
+- name: waiting for snapshot to be finished before querying
+ pause:
+ seconds: 10
+
+- name: get snapshots
+ cisco.aci.aci_config_snapshot:
+ <<: *create_snapshot
+ 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'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..22bcbcb79
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml
@@ -0,0 +1,148 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.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: create a snapshot - creation works
+ cisco.aci.aci_config_snapshot: &create_snapshot
+ 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
+ export_policy: anstest
+ include_secure: false
+ format: json
+ description: ansible test
+ register: create
+
+- name: update snapshot to include secure and use xml - update works
+ cisco.aci.aci_config_snapshot:
+ <<: *create_snapshot
+ max_count: 10
+ include_secure: true
+ format: xml
+ register: create_update
+
+- name: create a snapshot invalid max_count - error message
+ cisco.aci.aci_config_snapshot:
+ <<: *create_snapshot
+ max_count: 11
+ ignore_errors: true
+ register: invalid_max_count
+
+- name: create a snapshot invalid max_count - error message
+ cisco.aci.aci_config_snapshot:
+ <<: *create_snapshot
+ export_policy: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: missing_param
+
+- name: present assertion tests
+ assert:
+ that:
+ - create is not failed
+ - create is changed
+ - create.sent.configExportP.attributes.adminSt == "triggered"
+ - create_update is not failed
+ - create_update is changed
+ - create_update.current.0.configExportP.attributes.annotation == 'orchestrator:ansible'
+ - create_update.sent.configExportP.attributes.adminSt == 'triggered'
+ - create_update.sent.configExportP.attributes.format == 'xml'
+ - create_update.sent.configExportP.attributes.includeSecureFields == 'yes'
+ - invalid_max_count is failed
+ - invalid_max_count.msg == "Parameter 'max_count' must be a number between 1 and 10"
+ - missing_param is failed
+ - 'missing_param.msg == "state is present but all of the following are missing: export_policy"'
+ - create.job_details.attributes.dn == "uni/backupst/jobs-[uni/fabric/configexp-anstest]"
+ - create.job_details.attributes.name == "anstest"
+ - "'lastJobName' in create.job_details.attributes"
+
+- name: query with export_policy
+ cisco.aci.aci_config_snapshot: &query_snapshot
+ <<: *create_snapshot
+ state: query
+ register: query_export
+
+- name: generate snapshot name
+ set_fact:
+ test_snapshot: "{{ query_export.current.0.configSnapshotCont.children.0.configSnapshot.attributes.rn.strip('snapshot-') }}"
+
+- name: query with export_policy and snapshot
+ cisco.aci.aci_config_snapshot: &query_both
+ <<: *query_snapshot
+ snapshot: "{{ test_snapshot }}"
+ register: query_export_snapshot
+
+- name: query with snapshot - module add run- to snapshot
+ cisco.aci.aci_config_snapshot:
+ <<: *query_snapshot
+ export_policy: "{{ fake_var | default(omit) }}"
+ snapshot: "{{ test_snapshot.strip('run-') }}"
+ register: query_snapshot
+
+- name: query no params
+ cisco.aci.aci_config_snapshot:
+ <<: *query_snapshot
+ export_policy: "{{ fake_var | default(omit) }}"
+ register: query_all
+
+- name: query assertion tests
+ assert:
+ that:
+ - query_export is not failed
+ - query_export is not changed
+ - '"snapshots-[uni/fabric/configexp-anstest].json" in query_export.url'
+ - query_export.current.0.configSnapshotCont.attributes.name == "anstest"
+ - query_export.current.0.configSnapshotCont.children | length > 1
+ - query_export_snapshot is not failed
+ - query_export_snapshot is not changed
+ - '"snapshots-[uni/fabric/configexp-anstest]/snapshot-{{ test_snapshot }}.json" in query_export_snapshot.url'
+ - query_export_snapshot.current | length == 1
+ - query_snapshot is not failed
+ - query_snapshot is not changed
+ - '"class/configSnapshot.json" in query_snapshot.url'
+ - '"configSnapshot.name,\"{{ test_snapshot }}\"" in query_snapshot.filter_string'
+ - query_all is not failed
+ - query_all is not changed
+ - '"class/configSnapshot.json" in query_all.url'
+ - query_all.current | length > 1
+
+- name: delete works
+ cisco.aci.aci_config_snapshot: &delete
+ <<: *query_both
+ state: absent
+ register: delete_snapshot
+
+- name: delete works - idempotency
+ cisco.aci.aci_config_snapshot:
+ <<: *delete
+ register: delete_idempotent
+
+- name: delete missing param
+ cisco.aci.aci_config_snapshot:
+ <<: *delete
+ snapshot: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: delete_missing_param
+
+- name: absent assertion tests
+ assert:
+ that:
+ - delete_snapshot is not failed
+ - delete_snapshot is changed
+ - delete_snapshot.sent.configSnapshot.attributes.retire == 'yes'
+ - delete_snapshot.previous != []
+ - delete_snapshot.previous.0.configSnapshot.attributes.name == test_snapshot
+ - delete_idempotent is not failed
+ - delete_idempotent is not changed
+ - delete_idempotent.previous == []
+ - delete_missing_param is failed
+ - 'delete_missing_param.msg == "state is absent but all of the following are missing: snapshot"'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml
new file mode 100644
index 000000000..635f2d331
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml
@@ -0,0 +1,165 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: ensure tenant exists for tests to kick off
+ cisco.aci.aci_tenant: &aci_tenant_present
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+ tenant: ansible_test
+ state: present
+ register: tenant_present
+
+- name: create contract - check mode works
+ cisco.aci.aci_contract: &aci_contract_present
+ <<: *aci_tenant_present
+ contract: anstest
+ description: Ansible Test
+ check_mode: true
+ register: present_check_mode
+
+- name: create contract - creation works
+ cisco.aci.aci_contract:
+ <<: *aci_contract_present
+ register: contract_present
+
+- name: create contract - idempotency works
+ cisco.aci.aci_contract:
+ <<: *aci_contract_present
+ register: present_idempotent
+
+- name: update contract - update works
+ cisco.aci.aci_contract:
+ <<: *aci_contract_present
+ scope: application-profile
+ register: present_update
+
+- name: create contract - used for query
+ cisco.aci.aci_contract:
+ <<: *aci_contract_present
+ contract: anstest2
+
+- name: missing param - failure message works
+ cisco.aci.aci_contract:
+ <<: *aci_tenant_present
+ ignore_errors: true
+ register: present_missing_param
+
+- name: present assertions
+ assert:
+ that:
+ - present_check_mode is changed
+ - present_check_mode.previous == []
+ - present_check_mode.sent.vzBrCP.attributes.name == 'anstest'
+ - present_check_mode.sent.vzBrCP.attributes.descr == 'Ansible Test'
+ - contract_present is changed
+ - contract_present.current.0.vzBrCP.attributes.annotation == 'orchestrator:ansible'
+ - contract_present.sent == present_check_mode.sent
+ - present_idempotent is not changed
+ - present_update is changed
+ - present_update.sent != present_update.proposed
+ - present_update.sent.vzBrCP.attributes.scope == "application-profile"
+ - present_missing_param is failed
+ - 'present_missing_param.msg == "state is present but all of the following are missing: contract"'
+
+- name: query contract
+ cisco.aci.aci_contract: &aci_contract_query
+ <<: *aci_contract_present
+ state: query
+ register: query_contract
+
+- name: query all in tenant
+ cisco.aci.aci_contract:
+ <<: *aci_contract_query
+ contract: "{{ fakevar | default(omit) }}"
+ register: query_tenant
+
+- name: query all with name
+ cisco.aci.aci_contract:
+ <<: *aci_contract_query
+ tenant: "{{ fakevar | default(omit) }}"
+ register: query_name
+
+- name: query all
+ cisco.aci.aci_contract:
+ <<: *aci_contract_query
+ tenant: "{{ fakevar | default(omit) }}"
+ contract: "{{ fakevar | default(omit) }}"
+ register: query_all
+
+- name: query assertions
+ assert:
+ that:
+ - query_contract is not changed
+ - query_contract.current | length == 1
+ - '"tn-ansible_test/brc-anstest.json" in query_contract.url'
+ - query_tenant is not changed
+ - query_tenant.current | length == 1
+ - query_tenant.current.0.fvTenant.children | length > 1
+ - '"rsp-subtree-class=vzBrCP" in query_tenant.filter_string'
+ - '"tn-ansible_test.json" in query_tenant.url'
+ - query_name is not changed
+ - query_name.current != []
+ - '"query-target-filter=eq(vzBrCP.name,\"anstest\")" in query_name.filter_string'
+ - '"class/vzBrCP.json" in query_name.url'
+ - query_all is not changed
+ - query_all.current | length > 1
+ - '"class/vzBrCP.json" in query_all.url'
+
+- name: delete contract - check mode works
+ cisco.aci.aci_contract: &aci_contract_absent
+ <<: *aci_contract_present
+ state: absent
+ check_mode: true
+ register: absent_check_mode
+
+- name: delete contract - deletion works
+ cisco.aci.aci_contract:
+ <<: *aci_contract_absent
+ register: contract_absent
+
+- name: delete contract - idempotency works
+ cisco.aci.aci_contract:
+ <<: *aci_contract_absent
+ register: absent_idempotent
+
+- name: delete contract - cleanup second contract
+ cisco.aci.aci_contract:
+ <<: *aci_contract_absent
+ contract: anstest2
+
+- name: missing param - fail message works
+ cisco.aci.aci_contract:
+ <<: *aci_contract_absent
+ tenant: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: absent_missing_param
+
+- name: absent assertions
+ assert:
+ that:
+ - absent_check_mode is changed
+ - absent_check_mode.previous != []
+ - contract_absent is changed
+ - contract_absent.previous == absent_check_mode.previous
+ - absent_idempotent is not changed
+ - absent_idempotent.previous == []
+ - absent_missing_param is failed
+ - 'absent_missing_param.msg == "state is absent but all of the following are missing: tenant"'
+
+- 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_contract_export/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml
new file mode 100644
index 000000000..5a1139947
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_export/tasks/main.yml
@@ -0,0 +1,140 @@
+# Author: Marcel Zehnder (@maercu)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant1 before we kickoff
+ cisco.aci.aci_tenant: &tenant1_absent
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+
+- name: Remove test tenant2 before we kickoff
+ cisco.aci.aci_tenant: &tenant2_absent
+ <<: *aci_info
+ tenant: ansible_test_2
+ state: absent
+
+# SETUP ENVIRONMENT
+- name: Create tenant1
+ cisco.aci.aci_tenant: &tenant1_present
+ <<: *tenant1_absent
+ state: present
+
+- name: Create tenant2
+ cisco.aci.aci_tenant: &tenant2_present
+ <<: *tenant2_absent
+ state: present
+
+- name: Configure source contracts
+ cisco.aci.aci_contract:
+ <<: *tenant1_present
+ contract: '{{ item }}'
+ scope: global
+ loop:
+ - src_contract1
+ - src_contract2
+
+# BEGIN WITH TESTS
+- name: Create contract interface (check_mode)
+ cisco.aci.aci_contract_export: &cif_present
+ <<: *tenant1_present
+ contract: src_contract1
+ destination_tenant: ansible_test_2
+ name: testcif1
+ check_mode: true
+ register: cm_add_intf
+
+- name: Create contract interface (normal_mode)
+ cisco.aci.aci_contract_export:
+ <<: *cif_present
+ register: nm_add_intf
+
+- name: Verify add_intf
+ assert:
+ that:
+ - cm_add_intf is changed
+ - nm_add_intf is changed
+ - cm_add_intf.previous == nm_add_intf.previous == []
+ - cm_add_intf.sent.vzCPIf.attributes.name == nm_add_intf.sent.vzCPIf.attributes.name == 'testcif1'
+ - nm_add_intf.current.0.vzCPIf.attributes.annotation == 'orchestrator:ansible'
+
+- name: Create interface again, check if idempotency works
+ cisco.aci.aci_contract_export:
+ <<: *cif_present
+ register: add_intf_again
+
+- name: Verify add_intf_again
+ assert:
+ that:
+ - add_intf_again is not changed
+
+# UPDATE CONTRACT INTERFACEE
+- name: Update interface
+ cisco.aci.aci_contract_export: &cif_update
+ <<: *cif_present
+ description: newdescription
+ register: update_intf
+
+- name: Verify update_intf
+ assert:
+ that:
+ - update_intf is changed
+ - update_intf.previous != []
+
+# CREATE ANOTHER CONTRACT INTERFACE
+- name: Add another profile
+ cisco.aci.aci_contract_export:
+ <<: *cif_present
+ name: testcif2
+ contract: src_contract2
+
+# QUERY ALL INTERFACES
+- name: Query all interfaces
+ cisco.aci.aci_contract_export:
+ <<: *aci_info
+ state: query
+ register: query_all_intfs
+
+- name: Verify query_all_intfs
+ assert:
+ that:
+ - query_all_intfs is not changed
+ - query_all_intfs.current|length > 1
+
+# QUERY A SPECIFIC INTERFACE
+- name: Query a specific interface
+ cisco.aci.aci_contract_export:
+ <<: *cif_update
+ state: query
+ register: query_spec_intf
+
+- name: Verify query_spec_intf
+ assert:
+ that:
+ - query_spec_intf is not changed
+ - query_spec_intf.current|length == 1
+
+# REMOVE INTERFACE
+- name: Remove interface
+ cisco.aci.aci_contract_export:
+ <<: *cif_update
+ state: absent
+ register: remove_intf
+
+- name: Verify remove_intf
+ assert:
+ that:
+ - remove_intf is changed
+ - remove_intf.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml
new file mode 100644
index 000000000..b7d53844c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml
@@ -0,0 +1,400 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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: Assure tenant removal after tests
+ block:
+ - name: ensure tenant is deleted for clean state
+ 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 contract exists for tests to kick off
+ cisco.aci.aci_contract: &aci_contract_present
+ <<: *aci_tenant_present
+ contract: anstest
+ register: contract_present
+
+ - name: create subject - check mode works
+ cisco.aci.aci_contract_subject: &aci_subject_present
+ <<: *aci_contract_present
+ subject: anstest
+ description: Ansible Test
+ check_mode: true
+ register: subject_present_check_mode
+
+ - name: create subject - creation works
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_present
+ register: subject_present
+
+ - name: create subject - idempotency works
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_present
+ register: subject_present_idempotent
+
+ - name: update subject - update works
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_present
+ description: Ansible Test
+ reverse_filter: "yes"
+ provider_match: at_most_one
+ priority: level2
+ register: subject_update
+
+ - name: create subject - try additional params
+ cisco.aci.aci_contract_subject: &aci_subject_present_2
+ <<: *aci_contract_present
+ subject: anstest2
+ reverse_filter: "no"
+ consumer_match: all
+ priority: level3
+ register: subject_present_2
+
+ - name: missing param - failure message works
+ cisco.aci.aci_contract_subject:
+ <<: *aci_tenant_present
+ ignore_errors: true
+ register: present_missing_param
+
+ - name: present assertions
+ assert:
+ that:
+ - subject_present_check_mode is changed
+ - subject_present_check_mode.sent.vzSubj.attributes.descr == 'Ansible Test'
+ - subject_present_check_mode.sent.vzSubj.attributes.name == 'anstest'
+ - subject_present is changed
+ - subject_present.previous == []
+ - subject_present.sent == subject_present_check_mode.sent
+ - subject_present.current.0.vzSubj.attributes.annotation == 'orchestrator:ansible'
+ - subject_present_idempotent is not changed
+ - subject_present_idempotent.previous != []
+ - subject_update is changed
+ - subject_update.sent != subject_update.proposed
+ - subject_update.sent.vzSubj.attributes.prio == 'level2'
+ - subject_update.sent.vzSubj.attributes.provMatchT == 'AtmostOne'
+ - subject_present_2 is changed
+ - subject_present_2.sent.vzSubj.attributes.consMatchT == 'All'
+ - subject_present_2.sent.vzSubj.attributes.name == 'anstest2'
+ - subject_present_2.sent.vzSubj.attributes.prio == 'level3'
+ - subject_present_2.sent.vzSubj.attributes.revFltPorts == 'no'
+ - present_missing_param is failed
+ - 'present_missing_param.msg == "state is present but all of the following are missing: contract, subject"'
+
+ - name: query tenant contract subject
+ cisco.aci.aci_contract_subject: &aci_query_subject
+ <<: *aci_subject_present
+ state: query
+ register: query_tenant_contract_subject
+
+ - name: query tenant contract
+ cisco.aci.aci_contract_subject:
+ <<: *aci_query_subject
+ subject: "{{ fakevar | default(omit) }}"
+ register: query_tenant_contract
+
+ - name: query tenant subject
+ cisco.aci.aci_contract_subject:
+ <<: *aci_query_subject
+ contract: "{{ fakevar | default(omit) }}"
+ register: query_tenant_subject
+
+ - name: query contract subject
+ cisco.aci.aci_contract_subject:
+ <<: *aci_query_subject
+ tenant: "{{ fakevar | default(omit) }}"
+ register: query_contract_subject
+
+ - name: query tenant
+ cisco.aci.aci_contract_subject:
+ <<: *aci_tenant_present
+ state: query
+ register: query_tenant
+
+ - name: query contract
+ cisco.aci.aci_contract_subject:
+ <<: *aci_contract_present
+ state: query
+ tenant: "{{ fakevar | default(omit) }}"
+ register: query_contract
+
+ - name: query subject
+ cisco.aci.aci_contract_subject:
+ <<: *aci_query_subject
+ tenant: "{{ fakevar | default(omit) }}"
+ contract: "{{ fakevar | default(omit) }}"
+ register: query_subject
+
+ - name: query all
+ cisco.aci.aci_contract_subject:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: query assertions
+ assert:
+ that:
+ - query_tenant_contract_subject is not changed
+ - query_tenant_contract_subject.current | length == 1
+ - query_tenant_contract_subject.current.0.vzSubj.attributes.name == "anstest"
+ - '"tn-ansible_test/brc-anstest/subj-anstest.json" in query_tenant_contract_subject.url'
+ - query_tenant_contract is not changed
+ - query_tenant_contract.current | length == 1
+ - query_tenant_contract.current.0.vzBrCP.attributes.name == "anstest"
+ - query_tenant_contract.current.0.vzBrCP.children | length == 2
+ - '"?rsp-subtree=full&rsp-subtree-class=vzInTerm,vzOutTerm,vzSubj" in query_tenant_contract.filter_string'
+ - '"tn-ansible_test/brc-anstest.json" in query_tenant_contract.url'
+ - query_tenant_subject is not changed
+ - query_tenant_subject.current | length == 1
+ - query_tenant_subject.current.0.fvTenant.attributes.name == "ansible_test"
+ - query_tenant_subject.current.0.fvTenant.children.0.vzBrCP.children | length == 1
+ - query_tenant_subject.current.0.fvTenant.children.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"
+ - '"rsp-subtree-filter=eq(vzSubj.name,\"anstest\")" in query_tenant_subject.filter_string'
+ - '"rsp-subtree-class=vzInTerm,vzOutTerm,vzSubj" in query_tenant_subject.filter_string'
+ - '"tn-ansible_test.json" in query_tenant_subject.url'
+ - query_contract_subject is not changed
+ - query_contract_subject.current.0.vzBrCP.attributes.name == "anstest"
+ - query_contract_subject.current.0.vzBrCP.children | length == 1
+ - query_contract_subject.current.0.vzBrCP.children.0.vzSubj.attributes.name == "anstest"
+ - '"query-target-filter=eq(vzBrCP.name,\"anstest\")" in query_contract_subject.filter_string'
+ - '"rsp-subtree-filter=eq(vzSubj.name,\"anstest\")" in query_contract_subject.filter_string'
+ - '"rsp-subtree-class=vzInTerm,vzOutTerm,vzSubj" in query_contract_subject.filter_string'
+ - '"class/vzBrCP.json" in query_contract_subject.url'
+ - query_tenant is not changed
+ - query_tenant.current | length == 1
+ - query_tenant.current.0.fvTenant.attributes.name == "ansible_test"
+ - '"rsp-subtree-class=vzBrCP,vzInTerm,vzOutTerm,vzSubj" in query_tenant.filter_string'
+ - '"tn-ansible_test.json" in query_tenant.url'
+ - query_contract is not changed
+ - query_contract.current.0.vzBrCP.attributes.name == "anstest"
+ - '"query-target-filter=eq(vzBrCP.name,\"anstest\")" in query_contract.filter_string'
+ - '"rsp-subtree-class=vzInTerm,vzOutTerm,vzSubj" in query_contract.filter_string'
+ - '"class/vzBrCP.json" in query_contract.url'
+ - query_subject is not changed
+ - query_subject.current.0.vzSubj.attributes.name == "anstest"
+ - '"query-target-filter=eq(vzSubj.name,\"anstest\")" in query_subject.filter_string'
+ - '"class/vzSubj.json" in query_subject.url'
+ - query_all is not changed
+ - query_all.current|length > 1
+ - query_all.current.0.vzSubj is defined
+ - '"class/vzSubj.json" in query_all.url'
+
+ - name: delete subject - check mode works
+ cisco.aci.aci_contract_subject: &aci_subject_absent
+ <<: *aci_subject_present
+ state: absent
+ check_mode: true
+ register: subject_absent_check_mode
+
+ - name: delete subject - deletion works
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_absent
+ register: subject_absent
+
+ - name: delete subject - idempotency works
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_absent
+ register: subject_absent_idempotent
+
+ - name: delete subject - cleanup
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_present_2
+ state: absent
+
+ - name: missing params - failure message works
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_absent
+ subject: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - subject_absent_check_mode is changed
+ - subject_absent_check_mode.previous != []
+ - subject_absent_check_mode.proposed == {}
+ - subject_absent is changed
+ - subject_absent.previous == subject_absent_check_mode.previous
+ - subject_absent_idempotent is not changed
+ - subject_absent_idempotent.previous == []
+ - absent_missing_param is failed
+ - 'absent_missing_param.msg == "state is absent but all of the following are missing: subject"'
+
+ - name: create contract 1
+ cisco.aci.aci_contract: &aci_contract1
+ <<: *aci_tenant_present
+ contract: contract1
+ register: contract_present
+
+ - name: create subject both (check_mode)
+ cisco.aci.aci_contract_subject: &aci_subject_both
+ <<: *aci_contract1
+ subject: subjectboth
+ check_mode: true
+ register: cm_subject_present_both_default
+
+ - name: create subject both
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_both
+ register: nm_subject_present_both_default
+
+ - name: create subject both again with direction both set
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_both
+ apply_both_direction: both
+ register: nm_subject_present_both_again
+
+ - name: create subject one-way (check_mode)
+ cisco.aci.aci_contract_subject: &aci_subject_one_way
+ <<: *aci_contract1
+ subject: subjectoneway
+ apply_both_direction: one-way
+ check_mode: true
+ register: cm_subject_present_one_way
+
+ - name: create subject one-way
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_one_way
+ register: nm_subject_present_one_way
+
+ - name: create subject one-way again
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_one_way
+ register: nm_subject_present_one_way_again
+
+ - name: subject assertions
+ assert:
+ that:
+ - cm_subject_present_both_default is changed
+ - nm_subject_present_both_default is changed
+ - nm_subject_present_both_default.current.0.vzSubj.attributes.name == "subjectboth"
+ - nm_subject_present_both_again is not changed
+ - cm_subject_present_one_way is changed
+ - nm_subject_present_one_way is changed
+ - nm_subject_present_one_way.current.0.vzSubj.attributes.name == "subjectoneway"
+ - nm_subject_present_one_way_again is not changed
+
+ - name: reverse subject both to one-way
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_both
+ apply_both_direction: one-way
+ register: nm_subject_reverse_to_one_way
+ ignore_errors: true
+
+ - name: reverse subject one-way to both
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_one_way
+ apply_both_direction: both
+ register: nm_subject_reverse_to_both
+ ignore_errors: true
+
+ - name: subject assertions
+ assert:
+ that:
+ - nm_subject_reverse_to_one_way is not changed
+ - nm_subject_reverse_to_one_way.msg == "Direction is not allowed, valid option is both."
+ - nm_subject_reverse_to_both is not changed
+ - nm_subject_reverse_to_both.msg == "Direction is not allowed, valid option is one-way."
+
+ - name: subject both with qos and dscp
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_both
+ priority: level1
+ dscp: AF11
+ register: nm_subject_both_qos_dscp
+
+ - name: subject both with change to qos
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_both
+ priority: unspecified
+ register: nm_subject_both_qos_change
+
+ - name: subject both with change to dscp
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_both
+ dscp: AF41
+ register: nm_subject_both_dscp_change
+
+ - name: subject one-way with qos and dscp
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_one_way
+ priority_consumer_to_provider: level2
+ dscp_consumer_to_provider: AF12
+ priority_provider_to_consumer: level3
+ dscp_provider_to_consumer: CS4
+ register: nm_subject_one_way_qos_dscp
+
+ - name: subject one-way with qos change
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_one_way
+ priority_consumer_to_provider: unspecified
+ priority_provider_to_consumer: level1
+ register: nm_subject_one_way_qos_change
+
+ - name: subject one-way with dscp change
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_one_way
+ dscp_consumer_to_provider: AF13
+ dscp_provider_to_consumer: CS1
+ register: nm_subject_one_way_dscp_change
+
+ - name: subject assertions
+ assert:
+ that:
+ - nm_subject_both_qos_dscp is changed
+ - nm_subject_both_qos_dscp.current.0.vzSubj.attributes.prio == "level1"
+ - nm_subject_both_qos_dscp.current.0.vzSubj.attributes.targetDscp == "AF11"
+ - nm_subject_both_qos_change is changed
+ - nm_subject_both_qos_change.current.0.vzSubj.attributes.prio == "unspecified"
+ - nm_subject_both_qos_change.current.0.vzSubj.attributes.targetDscp == "AF11"
+ - nm_subject_both_dscp_change is changed
+ - nm_subject_both_dscp_change.current.0.vzSubj.attributes.prio == "unspecified"
+ - nm_subject_both_dscp_change.current.0.vzSubj.attributes.targetDscp == "AF41"
+ - nm_subject_one_way_qos_dscp is changed
+ - nm_subject_one_way_qos_dscp.current.0.vzSubj.children.0.vzOutTerm.attributes.prio == "level3"
+ - nm_subject_one_way_qos_dscp.current.0.vzSubj.children.0.vzOutTerm.attributes.targetDscp == "CS4"
+ - nm_subject_one_way_qos_dscp.current.0.vzSubj.children.1.vzInTerm.attributes.prio == "level2"
+ - nm_subject_one_way_qos_dscp.current.0.vzSubj.children.1.vzInTerm.attributes.targetDscp == "AF12"
+ - nm_subject_one_way_qos_change is changed
+ - nm_subject_one_way_qos_change.current.0.vzSubj.children.0.vzOutTerm.attributes.prio == "level1"
+ - nm_subject_one_way_qos_change.current.0.vzSubj.children.0.vzOutTerm.attributes.targetDscp == "CS4"
+ - nm_subject_one_way_qos_change.current.0.vzSubj.children.1.vzInTerm.attributes.prio == "unspecified"
+ - nm_subject_one_way_qos_change.current.0.vzSubj.children.1.vzInTerm.attributes.targetDscp == "AF12"
+ - nm_subject_one_way_dscp_change is changed
+ - nm_subject_one_way_dscp_change.current.0.vzSubj.children.0.vzOutTerm.attributes.prio == "level1"
+ - nm_subject_one_way_dscp_change.current.0.vzSubj.children.0.vzOutTerm.attributes.targetDscp == "CS1"
+ - nm_subject_one_way_dscp_change.current.0.vzSubj.children.1.vzInTerm.attributes.prio == "unspecified"
+ - nm_subject_one_way_dscp_change.current.0.vzSubj.children.1.vzInTerm.attributes.targetDscp == "AF13"
+
+ always:
+ - 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_contract_subject_to_filter/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..f7e69e620
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml
@@ -0,0 +1,379 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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: 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: Assure tenant removal after tests
+ block:
+ - name: ensure tenant is deleted for clean state
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+ register: tenant_present
+
+ - 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 filter exists for tests to kick off
+ cisco.aci.aci_filter: &aci_filter_present_2
+ <<: *aci_tenant_present
+ filter: anstest2
+ register: filter_present_2
+
+ - name: ensure contract exists for tests to kick off
+ cisco.aci.aci_contract: &aci_contract_present
+ <<: *aci_tenant_present
+ contract: anstest
+ register: contract_present
+
+ - name: ensure subject exists for tests to kick off
+ cisco.aci.aci_contract_subject: &aci_subject_present
+ <<: *aci_contract_present
+ subject: anstest
+ register: subject_present
+
+ - name: create subject filter binding - check mode works
+ cisco.aci.aci_contract_subject_to_filter: &aci_subject_filter_present
+ <<: *aci_subject_present
+ filter: anstest
+ log: log
+ check_mode: true
+ register: subject_filter_present_check_mode
+
+ - name: create subject filter binding - creation works
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_present
+ register: subject_filter_present
+
+ - name: create subject filter binding - additional testing
+ cisco.aci.aci_contract_subject_to_filter: &aci_subject_filter_present_2
+ <<: *aci_subject_filter_present
+ filter: anstest2
+ register: subject_filter_present_2
+
+ - name: create subject filter binding - idempotency works
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_present
+ register: subject_filter_present_idempotent
+
+ - name: update subject filter binding - update works
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_present
+ log: none
+ register: subject_filter_update
+
+ - name: missing param - failure message works
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_tenant_present
+ ignore_errors: true
+ register: present_missing_param
+
+ - name: present assertions
+ assert:
+ that:
+ - subject_filter_present_check_mode is changed
+ - subject_filter_present_check_mode.previous == []
+ - subject_filter_present_check_mode.sent.vzRsSubjFiltAtt.attributes.directives == 'log'
+ - subject_filter_present_check_mode.sent.vzRsSubjFiltAtt.attributes.tnVzFilterName == 'anstest'
+ - subject_filter_present is changed
+ - subject_filter_present.previous == []
+ - subject_filter_present.sent == subject_filter_present_check_mode.sent
+ - subject_filter_present.current.0.vzRsSubjFiltAtt.attributes.annotation == 'orchestrator:ansible'
+ - subject_filter_present_2 is changed
+ - subject_filter_present_idempotent is not changed
+ - subject_filter_present_idempotent.previous != []
+ - subject_filter_update is changed
+ - subject_filter_update.sent.vzRsSubjFiltAtt.attributes.directives == ''
+ - present_missing_param is failed
+ - 'present_missing_param.msg == "state is present but all of the following are missing: contract, filter, subject"'
+
+ - name: query all
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fakevar | default(omit) }}"
+ register: query_all
+
+ - name: query binding
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_present
+ state: query
+ register: query_binding
+
+ - name: query assertions
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current | length > 1
+ - query_all.current.0.vzRsSubjFiltAtt is defined
+ - query_binding is not changed
+ - query_binding.current != []
+
+ - name: delete subject filter binding - check mode works
+ cisco.aci.aci_contract_subject_to_filter: &aci_subject_filter_absent
+ <<: *aci_subject_filter_present
+ state: absent
+ check_mode: true
+ register: subject_filter_absent_check_mode
+
+ - name: delete subject filter binding - deletion works
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_absent
+ register: subject_filter_absent
+
+ - name: delete subject filter binding - idempotency works
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_absent
+ register: subject_filter_absent_idempotent
+
+ - name: missing param - failure message works
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_absent
+ filter: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: absent_missing_param
+
+ - name: cleanup subject filter binding
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_filter_present_2
+ state: absent
+
+ - name: absent assertions
+ assert:
+ that:
+ - subject_filter_absent_check_mode is changed
+ - subject_filter_absent_check_mode.proposed == {}
+ - subject_filter_absent_check_mode.previous != []
+ - subject_filter_absent is changed
+ - subject_filter_absent.previous != []
+ - subject_filter_absent_idempotent is not changed
+ - subject_filter_absent_idempotent.previous == []
+ - absent_missing_param is failed
+ - 'absent_missing_param.msg == "state is absent but all of the following are missing: filter"'
+
+ - name: create filter 1
+ cisco.aci.aci_filter:
+ <<: *aci_tenant_present
+ filter: filter1
+
+ - name: create filter 2
+ cisco.aci.aci_filter:
+ <<: *aci_tenant_present
+ filter: filter2
+
+ - name: create contract 1
+ cisco.aci.aci_contract: &aci_contract1
+ <<: *aci_tenant_present
+ contract: contract1
+
+ - name: create subject both
+ cisco.aci.aci_contract_subject: &aci_subject_both
+ <<: *aci_contract1
+ subject: subjectboth
+ register: subject_both
+
+ - name: create subject one-way
+ cisco.aci.aci_contract_subject: &aci_subject_one_way
+ <<: *aci_contract1
+ subject: subjectoneway
+ apply_both_direction: one-way
+ register: nm_subject_present_one_way_again
+
+ - name: create subject filter with direction both as default (check_mode)
+ cisco.aci.aci_contract_subject_to_filter: &aci_subject_both_to_filter
+ <<: *aci_subject_both
+ filter: filter1
+ action: permit
+ directive: log
+ priority_override: level1
+ state: present
+ check_mode: true
+ register: cm_filter1_present_default
+
+ - name: apply subject filter1 with direction both as default
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_both_to_filter
+ register: nm_filter1_present_default
+
+ - name: apply subject filter1 with direction provider to consumer (error)
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_both_to_filter
+ direction: provider_to_consumer
+ register: nm_filter1_present_p2c
+ ignore_errors: true
+
+ - name: apply subject filter1 with direction consumer to provider (error)
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_both_to_filter
+ direction: consumer_to_provider
+ register: nm_filter1_present_c2p
+ ignore_errors: true
+
+ - name: apply subject filter1 with direction both set
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_both_to_filter
+ filter: filter1
+ direction: both
+ action: permit
+ directive: no_stats
+ priority_override: level2
+ state: present
+ register: nm_filter1_present_both
+
+ - name: apply subject filter2 with direction provider to consumer
+ cisco.aci.aci_contract_subject_to_filter: &aci_subject_one_way_to_filter
+ <<: *aci_contract1
+ subject: subjectoneway
+ filter: filter2
+ direction: provider_to_consumer
+ action: permit
+ directive: none
+ priority_override: level2
+ state: present
+ register: nm_filter2_present_p2c
+
+ - name: apply subject filter2 with direction consumer to provider
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_one_way_to_filter
+ direction: provider_to_consumer
+ register: nm_filter2_present_c2p
+
+ - name: apply subject filter2 with direction both (error)
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_one_way_to_filter
+ direction: both
+ register: nm_filter2_present_both
+ ignore_errors: true
+
+ - name: filter assertions
+ assert:
+ that:
+ - cm_filter1_present_default is changed
+ - nm_filter1_present_default is changed
+ - nm_filter1_present_default.current.0.vzRsSubjFiltAtt.attributes.action == "permit"
+ - nm_filter1_present_default.current.0.vzRsSubjFiltAtt.attributes.tnVzFilterName == "filter1"
+ - nm_filter1_present_default.current.0.vzRsSubjFiltAtt.attributes.priorityOverride == "level1"
+ - nm_filter1_present_default.current.0.vzRsSubjFiltAtt.attributes.directives == "log"
+ - nm_filter1_present_p2c is not changed
+ - nm_filter1_present_p2c.msg == "Direction is not allowed, valid option is both."
+ - nm_filter1_present_c2p is not changed
+ - nm_filter1_present_c2p.msg == "Direction is not allowed, valid option is both."
+ - nm_filter1_present_both is changed
+ - nm_filter1_present_both.current.0.vzRsSubjFiltAtt.attributes.action == "permit"
+ - nm_filter1_present_both.current.0.vzRsSubjFiltAtt.attributes.tnVzFilterName == "filter1"
+ - nm_filter1_present_both.current.0.vzRsSubjFiltAtt.attributes.priorityOverride == "level2"
+ - nm_filter1_present_both.current.0.vzRsSubjFiltAtt.attributes.directives == "no_stats"
+ - nm_filter2_present_p2c is changed
+ - nm_filter2_present_p2c.current.0.vzRsFiltAtt.attributes.action == "permit"
+ - nm_filter2_present_p2c.current.0.vzRsFiltAtt.attributes.tnVzFilterName == "filter2"
+ - nm_filter2_present_p2c.current.0.vzRsFiltAtt.attributes.priorityOverride == "level2"
+ - nm_filter2_present_p2c.current.0.vzRsFiltAtt.attributes.directives == ""
+ - nm_filter2_present_c2p is not changed
+ - nm_filter2_present_c2p.current.0.vzRsFiltAtt.attributes.action == "permit"
+ - nm_filter2_present_c2p.current.0.vzRsFiltAtt.attributes.tnVzFilterName == "filter2"
+ - nm_filter2_present_c2p.current.0.vzRsFiltAtt.attributes.priorityOverride == "level2"
+ - nm_filter2_present_c2p.current.0.vzRsFiltAtt.attributes.directives == ""
+ - nm_filter2_present_both.msg == "Direction is not allowed, valid option is consumer_to_provider or provider_to_consumer."
+
+ - 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 subject filter with action deny for non-cloud
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_both_to_filter
+ direction: both
+ action: deny
+ register: filter_present_deny_non_cloud_both
+
+ - name: create subject filter with action deny for non-cloud p2c
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_one_way_to_filter
+ direction: provider_to_consumer
+ action: deny
+ register: filter_present_deny_non_cloud_p2c
+
+ - name: create subject filter with action deny for non-cloud p2c
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_one_way_to_filter
+ direction: consumer_to_provider
+ action: deny
+ register: filter_present_deny_non_cloud_c2p
+
+ - name: filter subject with direction assertions
+ assert:
+ that:
+ - filter_present_deny_non_cloud_both is changed
+ - filter_present_deny_non_cloud_both.current.0.vzRsSubjFiltAtt.attributes.action == "deny"
+ - filter_present_deny_non_cloud_p2c is changed
+ - filter_present_deny_non_cloud_p2c.current.0.vzRsFiltAtt.attributes.action == "deny"
+ - filter_present_deny_non_cloud_c2p is changed
+ - filter_present_deny_non_cloud_c2p.current.0.vzRsFiltAtt.attributes.action == "deny"
+
+ - name: Execute tasks only for cloud sites
+ when: query_cloud.current | length > 0 # This condition will execute only cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: create subject filter with action deny casues error for cloud (error)
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_both_to_filter
+ action: deny
+ register: filter_present_deny_cloud
+ ignore_errors: true
+
+ - name: create subject filter with action deny for cloud p2c
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_one_way_to_filter
+ direction: provider_to_consumer
+ action: deny
+ register: filter_present_deny_cloud_p2c
+ ignore_errors: true
+
+ - name: create subject filter with action deny for cloud p2c
+ cisco.aci.aci_contract_subject_to_filter:
+ <<: *aci_subject_one_way_to_filter
+ direction: provider_to_consumer
+ action: deny
+ register: filter_present_deny_cloud_c2p
+ ignore_errors: true
+
+ - name: cloud assertions
+ assert:
+ that:
+ - filter_present_deny_cloud.msg.startswith("APIC Error 1: Invalid Configuration CLOUD_ONLY_PERMIT_ACTION_SUPPORTED")
+ - filter_present_deny_cloud_p2c.msg.startswith("APIC Error 1: Invalid Configuration CLOUD_ONLY_PERMIT_ACTION_SUPPORTED")
+ - filter_present_deny_cloud_c2p.msg.startswith("APIC Error 1: Invalid Configuration CLOUD_ONLY_PERMIT_ACTION_SUPPORTED")
+
+ always:
+ - 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_contract_subject_to_service_graph/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml
new file mode 100644
index 000000000..c9e41610f
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_service_graph/tasks/main.yml
@@ -0,0 +1,159 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: ensure tenant exists for tests to kick off
+ cisco.aci.aci_tenant: &aci_tenant_present
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+ tenant: ansible_test
+ state: present
+ register: tenant_present
+
+# CLEAN ENVIRONMENT
+- name: ensure contract is removed
+ cisco.aci.aci_contract:
+ <<: *aci_tenant_present
+ contract: anstest
+ state: absent
+ ignore_errors: true
+
+- name: ensure contract exists for tests to kick off
+ cisco.aci.aci_contract: &aci_contract_present
+ <<: *aci_tenant_present
+ contract: anstest
+ register: contract_present
+
+- name: ensure subject exists for tests to kick off
+ cisco.aci.aci_contract_subject: &aci_subject_present
+ <<: *aci_contract_present
+ subject: anstest
+ register: subject_present
+
+- name: create subject service graph binding - check mode works
+ cisco.aci.aci_contract_subject_to_service_graph: &aci_subject_service_graph_present
+ <<: *aci_subject_present
+ service_graph: anstest
+ check_mode: true
+ register: subject_service_graph_present_check_mode
+
+- name: create subject service graph binding - creation works
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_subject_service_graph_present
+ register: subject_service_graph_present
+
+- name: create subject service graph binding - idempotency works
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_subject_service_graph_present
+ register: subject_service_graph_present_idempotent
+
+- name: update subject service graph binding - update works
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_subject_service_graph_present
+ service_graph: anstest2
+ register: subject_service_graph_update
+
+- name: missing param - failure message works
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_tenant_present
+ ignore_errors: true
+ register: present_missing_param
+
+- name: present assertions
+ assert:
+ that:
+ - subject_service_graph_present_check_mode is changed
+ - subject_service_graph_present_check_mode.previous == []
+ - subject_service_graph_present_check_mode.sent.vzRsSubjGraphAtt.attributes.tnVnsAbsGraphName == 'anstest'
+ - subject_service_graph_present is changed
+ - subject_service_graph_present.previous == []
+ - subject_service_graph_present.sent == subject_service_graph_present_check_mode.sent
+ - subject_service_graph_present_idempotent is not changed
+ - subject_service_graph_present_idempotent.previous != []
+ - subject_service_graph_present.current.0.vzRsSubjGraphAtt.attributes.annotation == 'orchestrator:ansible'
+ - subject_service_graph_update is changed
+ - subject_service_graph_update.sent.vzRsSubjGraphAtt.attributes.tnVnsAbsGraphName == 'anstest2'
+ - present_missing_param is failed
+ - 'present_missing_param.msg == "state is present but all of the following are missing: contract, service_graph, subject"'
+
+- name: query all
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fakevar | default(omit) }}"
+ register: query_all
+
+- name: query binding
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_subject_service_graph_present
+ state: query
+ register: query_binding
+
+- name: query assertions
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current | length > 0
+ - query_all.current.0.vzRsSubjGraphAtt is defined
+ - query_binding is not changed
+ - query_binding.current != []
+
+- name: delete subject service graph binding - check mode works
+ cisco.aci.aci_contract_subject_to_service_graph: &aci_subject_service_graph_absent
+ <<: *aci_subject_service_graph_present
+ state: absent
+ check_mode: true
+ register: subject_service_graph_absent_check_mode
+
+- name: delete subject service graph binding - deletion works
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_subject_service_graph_absent
+ register: subject_service_graph_absent
+
+- name: delete subject service graph binding - idempotency works
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_subject_service_graph_absent
+ register: subject_service_graph_absent_idempotent
+
+- name: missing param - failure message works
+ cisco.aci.aci_contract_subject_to_service_graph:
+ <<: *aci_subject_service_graph_absent
+ service_graph: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: absent_missing_param
+
+- name: absent assertions
+ assert:
+ that:
+ - subject_service_graph_absent_check_mode is changed
+ - subject_service_graph_absent_check_mode.proposed == {}
+ - subject_service_graph_absent_check_mode.previous != []
+ - subject_service_graph_absent is changed
+ - subject_service_graph_absent.previous != []
+ - subject_service_graph_absent_idempotent is not changed
+ - subject_service_graph_absent_idempotent.previous == []
+ - absent_missing_param is failed
+ - 'absent_missing_param.msg == "state is absent but all of the following are missing: service_graph"'
+
+- name: cleanup contract
+ cisco.aci.aci_contract:
+ <<: *aci_contract_present
+ state: absent
+ when: contract_present is changed
+
+- name: cleanup tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present is changed \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..920a24969
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay/tasks/main.yml
@@ -0,0 +1,161 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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: debug
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Add a new tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+# CREATE DHCP RELAY
+- name: Add a new DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay
+ description: Ansible DHCP Relay
+ state: present
+ register: add_dhcp_relay
+
+- name: Verify DHCP Relay creation
+ assert:
+ that:
+ - add_dhcp_relay is changed
+ - add_dhcp_relay.current.0.dhcpRelayP.attributes.annotation == 'orchestrator:ansible'
+ - add_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay"
+ - add_dhcp_relay.current.0.dhcpRelayP.attributes.name == "ansible_dhcp_relay"
+ - add_dhcp_relay.current.0.dhcpRelayP.attributes.owner == "tenant"
+ - add_dhcp_relay.current.0.dhcpRelayP.attributes.descr == "Ansible DHCP Relay"
+
+# CREATE DHCP RELAY AGAIN TO TEST IDEMPOTENCE
+- name: Add DHCP relay policy again
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay
+ description: Ansible DHCP Relay
+ state: present
+ register: add_dhcp_relay_again
+
+- name: Verify DHCP Relay idempotence
+ assert:
+ that:
+ - add_dhcp_relay_again is not changed
+ - add_dhcp_relay_again.current.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay"
+ - add_dhcp_relay_again.current.0.dhcpRelayP.attributes.name == "ansible_dhcp_relay"
+ - add_dhcp_relay_again.current.0.dhcpRelayP.attributes.owner == "tenant"
+ - add_dhcp_relay_again.current.0.dhcpRelayP.attributes.descr == "Ansible DHCP Relay"
+
+# MODIFY DHCP RELAY
+- name: Update DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay
+ description: New Ansible DHCP Relay
+ state: present
+ register: update_dhcp_relay
+
+- name: Verify DHCP Relay change
+ assert:
+ that:
+ - update_dhcp_relay is changed
+ - update_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay"
+ - update_dhcp_relay.current.0.dhcpRelayP.attributes.name == "ansible_dhcp_relay"
+ - update_dhcp_relay.current.0.dhcpRelayP.attributes.owner == "tenant"
+ - update_dhcp_relay.current.0.dhcpRelayP.attributes.descr == "New Ansible DHCP Relay"
+
+# QUERY DHCP RELAY
+- name: Query DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay
+ state: query
+ register: query_dhcp_relay
+
+- name: Verify DHCP Relay query
+ assert:
+ that:
+ - query_dhcp_relay is not changed
+ - query_dhcp_relay.current.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay"
+ - query_dhcp_relay.current.0.dhcpRelayP.attributes.name == "ansible_dhcp_relay"
+ - query_dhcp_relay.current.0.dhcpRelayP.attributes.owner == "tenant"
+ - query_dhcp_relay.current.0.dhcpRelayP.attributes.descr == "New Ansible DHCP Relay"
+
+- name: Query all DHCP relays in ansible_tenant
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: query
+ register: query_dhcp_relay_all
+
+- name: Verify query idempotence
+ assert:
+ that:
+ - query_dhcp_relay_all is not changed
+
+# DELETE DHCP RELAY
+- name: Delete DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay
+ state: absent
+ register: delete_dhcp_relay
+
+- name: Verify DHCP Relay deletion
+ assert:
+ that:
+ - delete_dhcp_relay is changed
+ - delete_dhcp_relay.current == []
+ - delete_dhcp_relay.previous.0.dhcpRelayP.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay"
+ - delete_dhcp_relay.previous.0.dhcpRelayP.attributes.name == "ansible_dhcp_relay"
+ - delete_dhcp_relay.previous.0.dhcpRelayP.attributes.owner == "tenant"
+ - delete_dhcp_relay.previous.0.dhcpRelayP.attributes.descr == "New Ansible DHCP Relay"
+
+- name: Delete DHCP relay policy again to test idempotence
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay
+ state: absent
+ register: delete_dhcp_relay_again
+
+- name: Verify DHCP Relay deletion idempotence
+ assert:
+ that:
+ - delete_dhcp_relay_again is not changed
+
+# CLEAN ENVIRONMENT AGAIN
+- 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_dhcp_relay_provider/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..2edc45e51
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dhcp_relay_provider/tasks/main.yml
@@ -0,0 +1,570 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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: debug
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+# CLEAN ENVIRONMENT
+- name: Remove the ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Remove l2ext domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: ansible_l2dom
+ domain_type: l2dom
+ state: absent
+
+- name: Remove l3ext domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: ansible_l3dom
+ domain_type: l3dom
+ state: absent
+
+- 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 a new application profile
+ cisco.aci.aci_ap:
+ <<: *aci_info
+ tenant: ansible_tenant
+ ap: ansible_ap
+ description: Ansible AP
+ state: present
+
+ - name: Add a new EPG
+ cisco.aci.aci_epg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ ap: ansible_ap
+ epg: ansible_epg
+ description: Ansible EPG
+ state: present
+
+ - name: Add another new EPG
+ cisco.aci.aci_epg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ ap: ansible_ap
+ epg: ansible_epg_2
+ description: Ansible EPG
+ state: present
+
+ - name: Add a new BD
+ cisco.aci.aci_bd:
+ <<: *aci_info
+ tenant: ansible_tenant
+ bd: ansible_bd
+ state: present
+
+ - name: Add l2ext domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: ansible_l2dom
+ domain_type: l2dom
+ state: present
+
+ - name: Add a new l2out
+ cisco.aci.aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ domain: ansible_l2dom
+ bd: ansible_bd
+ vlan: 3200
+ state: present
+
+ - name: Add a new L2 external end point group
+ cisco.aci.aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_l2out_ext_net
+ state: present
+
+ - name: Add a new l3ext domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: ansible_l3dom
+ domain_type: l3dom
+ state: present
+
+ - name: Add a new VRF to a tenant
+ cisco.aci.aci_vrf:
+ <<: *aci_info
+ vrf: ansible_vrf
+ tenant: ansible_tenant
+ state: present
+
+ - name: Add a new L3Out
+ cisco.aci.aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ domain: ansible_l3dom
+ vrf: ansible_vrf
+ route_control:
+ - export
+ state: present
+
+ - name: Add a new ExtEpg
+ cisco.aci.aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ name: ansible_l3out_ext_net
+ state: present
+
+ # CREATE DHCP RELAY
+ - name: Add a new DHCP relay policy
+ cisco.aci.aci_dhcp_relay:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_dhcp_relay
+ description: Ansible DHCP Relay
+ state: present
+
+ # CREATE DHCP RELAY PROVIDERS
+ - name: Add a new DHCP relay App EPG provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ dhcp_server_addr: 10.20.30.40
+ state: present
+ register: add_epg_relay_provider
+
+ - name: Add a new DHCP relay L2out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ dhcp_server_addr: 10.20.30.41
+ state: present
+ register: add_l2_relay_provider
+
+ - name: Add a new DHCP relay L3out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_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_l3_relay_provider
+
+ - name: Add a new DHCP relay dn provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_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_dn_relay_provider
+
+ - name: Confirm DHCP relay provider creation
+ assert:
+ that:
+ - add_epg_relay_provider is changed
+ - add_epg_relay_provider.current.0.dhcpRsProv.attributes.annotation == 'orchestrator:ansible'
+ - add_epg_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]"
+ - add_epg_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.40"
+ - add_epg_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - add_l2_relay_provider is changed
+ - add_l2_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - add_l2_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.41"
+ - add_l2_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - add_l3_relay_provider is changed
+ - add_l3_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - add_l3_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.42"
+ - add_l3_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - add_dn_relay_provider is changed
+ - add_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]"
+ - add_dn_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.43"
+ - add_dn_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+
+ # ADD DHCP RELAY PROVIDERS AGAIN TO TEST IDEMPOTENCE
+ - name: Add DHCP relay App EPG provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ dhcp_server_addr: 10.20.30.40
+ state: present
+ register: add_epg_relay_provider_again
+
+ - name: Add DHCP relay L2out provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ dhcp_server_addr: 10.20.30.41
+ state: present
+ register: add_l2_relay_provider_again
+
+ - name: Add DHCP relay L3out provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_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_l3_relay_provider_again
+
+ - name: Add a new DHCP relay dn provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_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_dn_relay_provider_again
+
+ - name: Confirm DHCP relay provider idempotence
+ assert:
+ that:
+ - add_epg_relay_provider_again is not changed
+ - add_epg_relay_provider_again.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]"
+ - add_epg_relay_provider_again.current.0.dhcpRsProv.attributes.addr == "10.20.30.40"
+ - add_epg_relay_provider_again.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - add_l2_relay_provider_again is not changed
+ - add_l2_relay_provider_again.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - add_l2_relay_provider_again.current.0.dhcpRsProv.attributes.addr == "10.20.30.41"
+ - add_l2_relay_provider_again.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - add_l3_relay_provider_again is not changed
+ - add_l3_relay_provider_again.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - add_l3_relay_provider_again.current.0.dhcpRsProv.attributes.addr == "10.20.30.42"
+ - add_l3_relay_provider_again.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - add_dn_relay_provider_again is not changed
+ - add_dn_relay_provider_again.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]"
+ - add_dn_relay_provider_again.current.0.dhcpRsProv.attributes.addr == "10.20.30.43"
+ - add_dn_relay_provider_again.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+
+ # MODIFY DHCP RELAY PROVIDERS
+ - name: Update DHCP relay App EPG provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ dhcp_server_addr: 10.20.30.50
+ state: present
+ register: update_epg_relay_provider
+
+ - name: Update DHCP relay L2out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ dhcp_server_addr: 10.20.30.51
+ state: present
+ register: update_l2_relay_provider
+
+ - name: Update DHCP relay L3out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_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.52
+ state: present
+ register: update_l3_relay_provider
+
+ - name: Update DHCP relay dn provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: dn
+ dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ dhcp_server_addr: 10.20.30.53
+ state: present
+ register: update_dn_relay_provider
+
+ - name: Confirm DHCP relay provider update
+ assert:
+ that:
+ - update_epg_relay_provider is changed
+ - update_epg_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]"
+ - update_epg_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.50"
+ - update_epg_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - update_l2_relay_provider is changed
+ - update_l2_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - update_l2_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.51"
+ - update_l2_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - update_l3_relay_provider is changed
+ - update_l3_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - update_l3_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.52"
+ - update_l3_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - update_dn_relay_provider is changed
+ - update_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]"
+ - 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:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ state: query
+ register: query_epg_relay_provider
+
+ - name: Query DHCP relay L2out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ state: query
+ register: query_l2_relay_provider
+
+ - name: Query DHCP relay L3out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l3_external
+ l3out_name: ansible_l3out
+ external_net: ansible_l3out_ext_net
+ state: query
+ register: query_l3_relay_provider
+
+ - name: Query DHCP relay dn provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: dn
+ dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ state: query
+ register: query_dn_relay_provider
+
+ - name: Confirm DHCP relay provider query
+ assert:
+ that:
+ - query_epg_relay_provider is not changed
+ - query_epg_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]"
+ - query_epg_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.50"
+ - query_epg_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - query_l2_relay_provider is not changed
+ - query_l2_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - query_l2_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.51"
+ - query_l2_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - query_l3_relay_provider is not changed
+ - query_l3_relay_provider.current.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - query_l3_relay_provider.current.0.dhcpRsProv.attributes.addr == "10.20.30.52"
+ - query_l3_relay_provider.current.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - query_dn_relay_provider is not changed
+ - 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"
+
+ # DELETE DHCP RELAY PROVIDERS
+ - name: Delete DHCP relay App EPG provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ state: absent
+ register: delete_epg_relay_provider
+
+ - name: Delete DHCP relay L2out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ state: absent
+ register: delete_l2_relay_provider
+
+ - name: Delete DHCP relay L3out provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l3_external
+ provider_tenant: ansible_tenant
+ l3out_name: ansible_l3out
+ external_net: ansible_l3out_ext_net
+ state: absent
+ register: delete_l3_relay_provider
+
+ - name: Delete DHCP relay dn provider
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: dn
+ dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ state: absent
+ register: delete_dn_relay_provider
+
+
+ - name: Confirm DHCP relay provider removal
+ assert:
+ that:
+ - delete_epg_relay_provider is changed
+ - delete_epg_relay_provider.current == []
+ - delete_epg_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg]"
+ - delete_epg_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.50"
+ - delete_epg_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg"
+ - delete_l2_relay_provider is changed
+ - delete_l2_relay_provider.current == []
+ - delete_l2_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net]"
+ - delete_l2_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.51"
+ - delete_l2_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_l2out_ext_net"
+ - delete_l3_relay_provider is changed
+ - delete_l3_relay_provider.current == []
+ - delete_l3_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net]"
+ - delete_l3_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.52"
+ - delete_l3_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_l3out_ext_net"
+ - delete_dn_relay_provider is changed
+ - delete_dn_relay_provider.previous.0.dhcpRsProv.attributes.dn == "uni/tn-ansible_tenant/relayp-ansible_dhcp_relay/rsprov-[uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2]"
+ - delete_dn_relay_provider.previous.0.dhcpRsProv.attributes.addr == "10.20.30.53"
+ - delete_dn_relay_provider.previous.0.dhcpRsProv.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+
+ # DELETE DHCP RELAY PROVIDERS AGAIN TO TEST IDEMPOTENCE
+ - name: Delete DHCP relay App EPG provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: epg
+ anp: ansible_ap
+ app_epg: ansible_epg
+ state: absent
+ register: delete_epg_relay_provider_again
+
+ - name: Delete DHCP relay L2out provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l2_external
+ l2out_name: ansible_l2out
+ external_net: ansible_l2out_ext_net
+ state: absent
+ register: delete_l2_relay_provider_again
+
+ - name: Delete DHCP relay L3out provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: l3_external
+ provider_tenant: ansible_tenant
+ l3out_name: ansible_l3out
+ external_net: ansible_l3out_ext_net
+ state: absent
+ register: delete_l3_relay_provider_again
+
+ - name: Delete DHCP relay dn provider again
+ cisco.aci.aci_dhcp_relay_provider:
+ <<: *aci_info
+ tenant: ansible_tenant
+ relay_policy: ansible_dhcp_relay
+ epg_type: dn
+ dn: "uni/tn-ansible_tenant/ap-ansible_ap/epg-ansible_epg_2"
+ state: absent
+ register: delete_dn_relay_provider_again
+
+ - name: Confirm DHCP relay provider removal
+ assert:
+ that:
+ - delete_epg_relay_provider_again is not changed
+ - delete_l2_relay_provider_again is not changed
+ - delete_l3_relay_provider_again is not changed
+ - delete_dn_relay_provider_again is not changed
+
+ # CLEAN ENVIRONMENT AGAIN
+ - name: Remove the ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+ - name: Remove l2ext domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: ansible_l2dom
+ domain_type: l2dom
+ state: absent
+
+ - name: Remove l3ext domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: ansible_l3dom
+ domain_type: l3dom
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..2d3de4dd0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_domain/tasks/main.yml
@@ -0,0 +1,169 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove DNS profile if it already exists
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: absent
+ delegate_to: localhost
+
+# ADD DNS PROFILE
+- name: Add DNS profile
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: present
+ delegate_to: localhost
+
+# ADD DNS DOMAIN
+- name: Add a new DNS domain
+ cisco.aci.aci_dns_domain:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ domain: example.com
+ default: false
+ state: present
+ delegate_to: localhost
+ register: add_dns_domain
+
+- name: Verify DNS domain creation
+ assert:
+ that:
+ - add_dns_domain is changed
+ - add_dns_domain.current.0.dnsDomain.attributes.annotation == 'orchestrator:ansible'
+ - add_dns_domain.current.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com"
+ - add_dns_domain.current.0.dnsDomain.attributes.name == "example.com"
+ - add_dns_domain.current.0.dnsDomain.attributes.isDefault == "no"
+
+# ADD DNS DOMAIN AGAIN TO TEST IDEMPOTENCE
+- name: Add DNS domain again
+ cisco.aci.aci_dns_domain:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ domain: example.com
+ default: false
+ state: present
+ delegate_to: localhost
+ register: add_dns_domain_again
+
+- name: Verify DNS domain creation idempotence
+ assert:
+ that:
+ - add_dns_domain_again is not changed
+ - add_dns_domain_again.current.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com"
+ - add_dns_domain_again.current.0.dnsDomain.attributes.name == "example.com"
+ - add_dns_domain_again.current.0.dnsDomain.attributes.isDefault == "no"
+
+# MODIFY DNS DOMAIN
+- name: Update DNS domain
+ cisco.aci.aci_dns_domain:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ domain: example.com
+ default: true
+ state: present
+ delegate_to: localhost
+ register: update_dns_domain
+
+- name: Verify DNS domain update
+ assert:
+ that:
+ - update_dns_domain is changed
+ - update_dns_domain.current.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com"
+ - update_dns_domain.current.0.dnsDomain.attributes.name == "example.com"
+ - update_dns_domain.current.0.dnsDomain.attributes.isDefault == "yes"
+
+# QUERY DNS DOMAIN
+- name: Query DNS domain
+ cisco.aci.aci_dns_domain:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ domain: example.com
+ state: query
+ delegate_to: localhost
+ register: query_dns_domain
+
+- name: Verify DNS domain attributes
+ assert:
+ that:
+ - query_dns_domain is not changed
+ - query_dns_domain.current.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com"
+ - query_dns_domain.current.0.dnsDomain.attributes.name == "example.com"
+ - query_dns_domain.current.0.dnsDomain.attributes.isDefault == "yes"
+
+# QUERY ALL DNS DOMAINS WITHIN THE PROFILE
+- name: Query all DNS domains within the profile
+ cisco.aci.aci_dns_domain:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ state: query
+ delegate_to: localhost
+ register: query_dns_domain_all
+
+- name: Verify DNS domain query idempotence
+ assert:
+ that:
+ - query_dns_domain_all is not changed
+
+# DELETE DNS DOMAIN
+- name: Remove DNS Domain
+ cisco.aci.aci_dns_domain:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ domain: example.com
+ state: absent
+ delegate_to: localhost
+ register: delete_dns_domain
+
+- name: Verify DNS domain deletion
+ assert:
+ that:
+ - delete_dns_domain is changed
+ - delete_dns_domain.current == []
+ - delete_dns_domain.previous.0.dnsDomain.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/dom-example.com"
+ - delete_dns_domain.previous.0.dnsDomain.attributes.name == "example.com"
+ - delete_dns_domain.previous.0.dnsDomain.attributes.isDefault == "yes"
+
+# DELETE DNS DOMAIN AGAIN TO TEST IDEMPOTENCE
+- name: Remove DNS Domain
+ cisco.aci.aci_dns_domain:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ domain: example.com
+ state: absent
+ delegate_to: localhost
+ register: delete_dns_domain_again
+
+- name: Verify DNS domain deletion idempotence
+ assert:
+ that:
+ - delete_dns_domain_again is not changed
+
+# CLEAN ENVIRONMENT
+- name: Remove DNS profile if it already exists
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: absent
+ delegate_to: localhost
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_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_dns_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/tasks/main.yml
new file mode 100644
index 000000000..126bb27a6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_profile/tasks/main.yml
@@ -0,0 +1,107 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# ADD DNS PROFILE
+- name: Add DNS profile
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: present
+ register: add_dns_profile
+
+- name: Verify that DNS profile has been created with correct attributes
+ assert:
+ that:
+ - add_dns_profile is changed
+ - add_dns_profile.current.0.dnsProfile.attributes.annotation == 'orchestrator:ansible'
+ - add_dns_profile.current.0.dnsProfile.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile"
+ - add_dns_profile.current.0.dnsProfile.attributes.name == "ansible_dns_profile"
+
+# ADD DNS PROFILE AGAIN TO TEST IDEMPOTENCE
+- name: Add DNS profile again
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: present
+ register: add_dns_profile_again
+
+- name: Verify that DNS profile creation idempotence
+ assert:
+ that:
+ - add_dns_profile_again is not changed
+ - add_dns_profile_again.current.0.dnsProfile.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile"
+ - add_dns_profile_again.current.0.dnsProfile.attributes.name == "ansible_dns_profile"
+
+# QUERY DNS PROFILE
+- name: Query the DNS profile
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: query
+ register: query_dns_profile
+
+- name: Verify DNS profile
+ assert:
+ that:
+ - query_dns_profile is not changed
+ - query_dns_profile.current.0.dnsProfile.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile"
+ - query_dns_profile.current.0.dnsProfile.attributes.name == "ansible_dns_profile"
+
+- name: Query all DNS profiles
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ state: query
+ register: query_dns_profile_all
+
+- name: Verify query idempotence
+ assert:
+ that:
+ - query_dns_profile_all is not changed
+
+# DELETE DNS PROFILE
+- name: Remove the DNS profile
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ name: ansible_dns_profile
+ state: absent
+ register: remove_dns_profile
+
+- name: Verify DNS profile removal
+ assert:
+ that:
+ - remove_dns_profile is changed
+ - remove_dns_profile.current == []
+ - remove_dns_profile.previous.0.dnsProfile.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile"
+ - remove_dns_profile.previous.0.dnsProfile.attributes.name == "ansible_dns_profile"
+
+# DELETE DNS PROFILE AGAIN TO TEST IDEMPOTENCE
+- name: Remove the DNS profile again
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ name: ansible_dns_profile
+ state: absent
+ register: remove_dns_profile_again
+
+- name: Verify DNS profile removal idempotence
+ assert:
+ that:
+ - remove_dns_profile_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..8deca651c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_dns_provider/tasks/main.yml
@@ -0,0 +1,169 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove DNS profile if it already exists
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: absent
+ delegate_to: localhost
+
+# ADD DNS PROFILE
+- name: Add DNS profile
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: present
+ delegate_to: localhost
+
+# ADD DNS PROVIDER
+- name: Add a new DNS provider
+ cisco.aci.aci_dns_provider:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ addr: 10.20.30.40
+ preferred: false
+ state: present
+ delegate_to: localhost
+ register: add_dns_provider
+
+- name: Verify DNS provider creation
+ assert:
+ that:
+ - add_dns_provider is changed
+ - add_dns_provider.current.0.dnsProv.attributes.annotation == 'orchestrator:ansible'
+ - add_dns_provider.current.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]"
+ - add_dns_provider.current.0.dnsProv.attributes.addr == "10.20.30.40"
+ - add_dns_provider.current.0.dnsProv.attributes.preferred == "no"
+
+# ADD DNS PROVIDER AGAIN TO TEST IDEMPOTENCE
+- name: Add a new DNS provider again
+ cisco.aci.aci_dns_provider:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ addr: 10.20.30.40
+ preferred: false
+ state: present
+ delegate_to: localhost
+ register: add_dns_provider_again
+
+- name: Verify DNS provider creation idempotence
+ assert:
+ that:
+ - add_dns_provider_again is not changed
+ - add_dns_provider_again.current.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]"
+ - add_dns_provider_again.current.0.dnsProv.attributes.addr == "10.20.30.40"
+ - add_dns_provider_again.current.0.dnsProv.attributes.preferred == "no"
+
+# MODIFY DNS PROVIDER
+- name: Update DNS provider
+ cisco.aci.aci_dns_provider:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ addr: 10.20.30.40
+ preferred: true
+ state: present
+ delegate_to: localhost
+ register: update_dns_provider
+
+- name: Verify DNS provider update
+ assert:
+ that:
+ - update_dns_provider is changed
+ - update_dns_provider.current.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]"
+ - update_dns_provider.current.0.dnsProv.attributes.addr == "10.20.30.40"
+ - update_dns_provider.current.0.dnsProv.attributes.preferred == "yes"
+
+# QUERY DNS PROVIDER
+- name: Query DNS provider
+ cisco.aci.aci_dns_provider:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ addr: 10.20.30.40
+ state: query
+ delegate_to: localhost
+ register: query_dns_provider
+
+- name: Verify DNS provider attributes
+ assert:
+ that:
+ - query_dns_provider is not changed
+ - query_dns_provider.current.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]"
+ - query_dns_provider.current.0.dnsProv.attributes.addr == "10.20.30.40"
+ - query_dns_provider.current.0.dnsProv.attributes.preferred == "yes"
+
+# QUERY ALL DNS PROVIDERS WITHIN THE PROFILE
+- name: Query all DNS providers within profile
+ cisco.aci.aci_dns_provider:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ state: query
+ delegate_to: localhost
+ register: query_dns_provider_all
+
+- name: Verify DNS provider query idempotence
+ assert:
+ that:
+ - query_dns_provider_all is not changed
+
+# DELETE DNS PROVIDER
+- name: Delete DNS provider
+ cisco.aci.aci_dns_provider:
+ <<: *aci_info
+ dns_profile: ansible_dns_profile
+ addr: 10.20.30.40
+ state: absent
+ delegate_to: localhost
+ register: delete_dns_provider
+
+- name: Verify DNS provider deletion
+ assert:
+ that:
+ - delete_dns_provider is changed
+ - delete_dns_provider.current == []
+ - delete_dns_provider.previous.0.dnsProv.attributes.dn == "uni/fabric/dnsp-ansible_dns_profile/prov-[10.20.30.40]"
+ - delete_dns_provider.previous.0.dnsProv.attributes.addr == "10.20.30.40"
+ - delete_dns_provider.previous.0.dnsProv.attributes.preferred == "yes"
+
+# DELETE DNS PROVIDER AGAIN TO TEST IDEMPOTENCE
+- name: Delete DNS provider again
+ cisco.aci.aci_dns_provider:
+ <<: *aci_info
+ 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
+ assert:
+ that:
+ - delete_dns_provider_again is not changed
+
+# CLEAN ENVIRONMENT
+- name: Remove DNS profile if it already exists
+ cisco.aci.aci_dns_profile:
+ <<: *aci_info
+ profile_name: ansible_dns_profile
+ state: absent
+ delegate_to: localhost
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml
new file mode 100644
index 000000000..2e2a8eb0b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml
@@ -0,0 +1,299 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove FC domain
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: fc_dom
+ domain_type: fc
+ state: absent
+
+
+# ADD DOMAIN
+- name: Add FC domain (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: fc_dom
+ domain_type: fc
+ state: present
+ check_mode: true
+ register: cm_add_domain
+
+- name: Add FC domain (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain
+
+- name: Verify FC add_domain
+ assert:
+ that:
+ - cm_add_domain is changed
+ - nm_add_domain is changed
+ - cm_add_domain.sent.fcDomP.attributes.name == nm_add_domain.sent.fcDomP.attributes.name == 'fc_dom'
+ - cm_add_domain.proposed.fcDomP.attributes.name == nm_add_domain.proposed.fcDomP.attributes.name == 'fc_dom'
+ - cm_add_domain.current == cm_add_domain.previous == nm_add_domain.previous == []
+ - nm_add_domain.current.0.fcDomP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_domain.current.0.fcDomP.attributes.name == 'fc_dom'
+ - nm_add_domain.current.0.fcDomP.attributes.dn == 'uni/fc-fc_dom'
+
+- name: Add FC domain again (check_mode)
+ cisco.aci.aci_domain: *domain_present
+ check_mode: true
+ register: cm_add_domain_again
+
+- name: Add FC domain again (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain_again
+
+- name: Verify FC add_domain_again
+ assert:
+ that:
+ - cm_add_domain_again is not changed
+ - nm_add_domain_again is not changed
+
+- name: Update FC domain with incorrect parameter vm_provider (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vm_provider
+
+- name: Update FC domain with incorrect parameter vm_provider (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ ignore_errors: true
+ register: nm_incorrect_vm_provider
+
+- name: Update FC domain with incorrect parameter encap_mode (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_encap_mode
+
+- name: Update FC domain with incorrect parameter encap_mode (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ ignore_errors: true
+ register: nm_incorrect_encap_mode
+
+- name: Update FC domain with incorrect parameter multicast_address (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_multicast_address
+
+- name: Update FC domain with incorrect parameter multicast_address (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ ignore_errors: true
+ register: nm_incorrect_multicast_address
+
+- name: Update FC domain with incorrect parameter vswitch (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vswitch
+
+- name: Update FC domain with incorrect parameter vswitch (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ ignore_errors: true
+ register: nm_incorrect_vswitch
+
+- name: Update FC domain with incorrect parameter dscp (check mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ dscp: unspecified
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_dscp
+
+- name: Update FC domain with incorrect parameter dscp (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ dscp: unspecified
+ ignore_errors: true
+ register: nm_incorrect_dscp
+
+- name: Update FC domain with incorrect parameter access_mode (check mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ access_mode: read-write
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_access_mode
+
+- name: Update FC domain with incorrect parameter access_mode (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ access_mode: read-write
+ ignore_errors: true
+ register: nm_incorrect_access_mode
+
+- name: Update FC domain with incorrect parameter enable_vm_folder (check mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ enable_vm_folder: true
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_enable_vm_folder
+
+- name: Update FC domain with incorrect parameter enable_vm_folder (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ enable_vm_folder: true
+ ignore_errors: true
+ register: nm_incorrect_enable_vm_folder
+
+- name: Verify incorrect parameter
+ assert:
+ that:
+ - cm_incorrect_vm_provider.msg == "Domain type 'fc' cannot have parameter 'vm_provider'"
+ - nm_incorrect_vm_provider.msg == "Domain type 'fc' cannot have parameter 'vm_provider'"
+ - cm_incorrect_encap_mode.msg == "Domain type 'fc' cannot have parameter 'encap_mode'"
+ - nm_incorrect_encap_mode.msg == "Domain type 'fc' cannot have parameter 'encap_mode'"
+ - cm_incorrect_multicast_address.msg == "Domain type 'fc' cannot have parameter 'multicast_address'"
+ - nm_incorrect_multicast_address.msg == "Domain type 'fc' cannot have parameter 'multicast_address'"
+ - cm_incorrect_vswitch.msg == "Domain type 'fc' cannot have parameter 'vswitch'"
+ - nm_incorrect_vswitch.msg == "Domain type 'fc' cannot have parameter 'vswitch'"
+ - cm_incorrect_dscp.msg == "DSCP values can only be assigned to 'l2ext and 'l3ext' domains"
+ - nm_incorrect_dscp.msg == "DSCP values can only be assigned to 'l2ext and 'l3ext' domains"
+ - cm_incorrect_access_mode.msg == "Domain type 'fc' cannot have parameter 'access_mode'"
+ - nm_incorrect_access_mode.msg == "Domain type 'fc' cannot have parameter 'access_mode'"
+ - cm_incorrect_enable_vm_folder.msg == "Domain type 'fc' cannot have parameter 'enable_vm_folder'"
+ - nm_incorrect_enable_vm_folder.msg == "Domain type 'fc' cannot have parameter 'enable_vm_folder'"
+
+# QUERY ALL DOMAINS
+- name: Query all FC domains (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain_type: fc
+ state: query
+ check_mode: true
+ register: cm_query_all_domains
+
+- name: Query all FC domains (normal mode)
+ cisco.aci.aci_domain: *domain_query
+ register: nm_query_all_domains
+
+- name: Verify FC query_all_domains
+ assert:
+ that:
+ - cm_query_all_domains is not changed
+ - nm_query_all_domains is not changed
+ - cm_query_all_domains == nm_query_all_domains
+ - nm_query_all_domains.current|length >= 1
+
+
+# QUERY A DOMAIN
+- name: Query our FC domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: fc_dom
+ check_mode: true
+ register: cm_query_domain
+
+- name: Query our FC domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: fc_dom
+ register: nm_query_domain
+
+- name: Verify FC query_domain
+ assert:
+ that:
+ - cm_query_domain is not changed
+ - nm_query_domain is not changed
+ - cm_query_domain == nm_query_domain
+ - nm_query_domain.current.0.fcDomP.attributes.dn == 'uni/fc-fc_dom'
+ - nm_query_domain.current.0.fcDomP.attributes.name == 'fc_dom'
+
+
+# REMOVE DOMAIN
+- name: Remove FC domain (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain
+
+- name: Remove FC domain (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain
+
+- name: Verify FC remove_domain
+ assert:
+ that:
+ - cm_remove_domain is changed
+ - nm_remove_domain is changed
+ - cm_remove_domain.current.0.fcDomP.attributes.name == cm_remove_domain.previous.0.fcDomP.attributes.name == nm_remove_domain.previous.0.fcDomP.attributes.name == 'fc_dom'
+ - cm_remove_domain.current.0.fcDomP.attributes.dn == cm_remove_domain.previous.0.fcDomP.attributes.dn == nm_remove_domain.previous.0.fcDomP.attributes.dn == 'uni/fc-fc_dom'
+ - nm_remove_domain.current == []
+
+- name: Remove FC domain again (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain_again
+
+- name: Remove FC domain again (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain_again
+
+- name: Verify FC remove_domain_again
+ assert:
+ that:
+ - cm_remove_domain_again is not changed
+ - nm_remove_domain_again is not changed
+
+
+# QUERY NON-EXISTING DOMAIN
+- name: Query non-existing FC domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: fc_dom
+ check_mode: true
+ register: cm_query_non_domain
+
+- name: Query non-existing FC domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: fc_dom
+ register: nm_query_non_domain
+
+- name: Verify FC query_non_domain
+ assert:
+ that:
+ - cm_query_non_domain is not changed
+ - nm_query_non_domain is not changed
+ - cm_query_non_domain == nm_query_non_domain
+ - nm_query_non_domain.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml
new file mode 100644
index 000000000..4f0084174
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml
@@ -0,0 +1,248 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove L2 domain
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: l2_dom
+ domain_type: l2dom
+ state: absent
+
+
+# ADD DOMAIN
+- name: Add L2 domain (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: l2_dom
+ domain_type: l2dom
+ state: present
+ check_mode: true
+ register: cm_add_domain
+
+- name: Add L2 domain (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain
+
+- name: Verify L2 add_domain
+ assert:
+ that:
+ - cm_add_domain is changed
+ - nm_add_domain is changed
+ - cm_add_domain.sent.l2extDomP.attributes.name == nm_add_domain.sent.l2extDomP.attributes.name == 'l2_dom'
+ - cm_add_domain.proposed.l2extDomP.attributes.name == nm_add_domain.proposed.l2extDomP.attributes.name == 'l2_dom'
+ - cm_add_domain.current == cm_add_domain.previous == nm_add_domain.previous == []
+ - nm_add_domain.current.0.l2extDomP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_domain.current.0.l2extDomP.attributes.name == 'l2_dom'
+ - nm_add_domain.current.0.l2extDomP.attributes.dn == 'uni/l2dom-l2_dom'
+
+- name: Add L2 domain again (check_mode)
+ cisco.aci.aci_domain: *domain_present
+ check_mode: true
+ register: cm_add_domain_again
+
+- name: Add L2 domain again (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain_again
+
+- name: Verify L2 add_domain_again
+ assert:
+ that:
+ - cm_add_domain_again is not changed
+ - nm_add_domain_again is not changed
+
+- name: Update L2 domain with incorrect parameter vm_provider (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vm_provider
+
+- name: Update L2 domain with incorrect parameter vm_provider (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ ignore_errors: true
+ register: nm_incorrect_vm_provider
+
+- name: Update L2 domain with incorrect parameter encap_mode (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_encap_mode
+
+- name: Update L2 domain with incorrect parameter encap_mode (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ ignore_errors: true
+ register: nm_incorrect_encap_mode
+
+- name: Update L2 domain with incorrect parameter multicast_address (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_multicast_address
+
+- name: Update L2 domain with incorrect parameter multicast_address (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ ignore_errors: true
+ register: nm_incorrect_multicast_address
+
+- name: Update L2 domain with incorrect parameter vswitch (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vswitch
+
+- name: Update L2 domain with incorrect parameter vswitch (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ ignore_errors: true
+ register: nm_incorrect_vswitch
+
+- name: Verify incorrect parameter
+ assert:
+ that:
+ - cm_incorrect_vm_provider.msg == "Domain type 'l2dom' cannot have parameter 'vm_provider'"
+ - nm_incorrect_vm_provider.msg == "Domain type 'l2dom' cannot have parameter 'vm_provider'"
+ - cm_incorrect_encap_mode.msg == "Domain type 'l2dom' cannot have parameter 'encap_mode'"
+ - nm_incorrect_encap_mode.msg == "Domain type 'l2dom' cannot have parameter 'encap_mode'"
+ - cm_incorrect_multicast_address.msg == "Domain type 'l2dom' cannot have parameter 'multicast_address'"
+ - nm_incorrect_multicast_address.msg == "Domain type 'l2dom' cannot have parameter 'multicast_address'"
+ - cm_incorrect_vswitch.msg == "Domain type 'l2dom' cannot have parameter 'vswitch'"
+ - nm_incorrect_vswitch.msg == "Domain type 'l2dom' cannot have parameter 'vswitch'"
+
+# QUERY ALL DOMAINS
+- name: Query all L2 domains (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain_type: l2dom
+ state: query
+ check_mode: true
+ register: cm_query_all_domains
+
+- name: Query all L2 domains (normal mode)
+ cisco.aci.aci_domain: *domain_query
+ register: nm_query_all_domains
+
+- name: Verify L2 query_all_domains
+ assert:
+ that:
+ - cm_query_all_domains is not changed
+ - nm_query_all_domains is not changed
+ - cm_query_all_domains == nm_query_all_domains
+ - nm_query_all_domains.current|length >= 1
+
+
+# QUERY A DOMAIN
+- name: Query our L2 domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l2_dom
+ check_mode: true
+ register: cm_query_domain
+
+- name: Query our L2 domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l2_dom
+ register: nm_query_domain
+
+- name: Verify L2 query_domain
+ assert:
+ that:
+ - cm_query_domain is not changed
+ - nm_query_domain is not changed
+ - cm_query_domain == nm_query_domain
+ - nm_query_domain.current.0.l2extDomP.attributes.dn == 'uni/l2dom-l2_dom'
+ - nm_query_domain.current.0.l2extDomP.attributes.name == 'l2_dom'
+
+
+# REMOVE DOMAIN
+- name: Remove L2 domain (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain
+
+- name: Remove L2 domain (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain
+
+- name: Verify L2 remove_domain
+ assert:
+ that:
+ - cm_remove_domain is changed
+ - nm_remove_domain is changed
+ - cm_remove_domain.current.0.l2extDomP.attributes.dn == cm_remove_domain.previous.0.l2extDomP.attributes.dn == nm_remove_domain.previous.0.l2extDomP.attributes.dn == 'uni/l2dom-l2_dom'
+ - cm_remove_domain.current.0.l2extDomP.attributes.name == cm_remove_domain.previous.0.l2extDomP.attributes.name == nm_remove_domain.previous.0.l2extDomP.attributes.name == 'l2_dom'
+ - nm_remove_domain.current == []
+
+- name: Remove L2 domain again (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain_again
+
+- name: Remove L2 domain again (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain_again
+
+- name: Verify L2 remove_domain_again
+ assert:
+ that:
+ - cm_remove_domain_again is not changed
+ - nm_remove_domain_again is not changed
+
+
+# QUERY NON-EXISTING DOMAIN
+- name: Query non-existing L2 domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l2_dom
+ check_mode: true
+ register: cm_query_non_domain
+
+- name: Query non-existing L2 domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l2_dom
+ register: nm_query_non_domain
+
+- name: Verify L2 query_non_domain
+ assert:
+ that:
+ - cm_query_non_domain is not changed
+ - nm_query_non_domain is not changed
+ - cm_query_non_domain == nm_query_non_domain
+ - nm_query_non_domain.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml
new file mode 100644
index 000000000..61677d897
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml
@@ -0,0 +1,249 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove L3 domain
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: l3_dom
+ domain_type: l3dom
+ state: absent
+
+
+# ADD DOMAIN
+- name: Add L3 domain (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: l3_dom
+ domain_type: l3dom
+ state: present
+ check_mode: true
+ register: cm_add_domain
+
+- name: Add L3 domain (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain
+
+- name: Verify L3 add_domain
+ assert:
+ that:
+ - cm_add_domain is changed
+ - nm_add_domain is changed
+ - cm_add_domain.sent.l3extDomP.attributes.name == nm_add_domain.sent.l3extDomP.attributes.name == 'l3_dom'
+ - cm_add_domain.proposed.l3extDomP.attributes.name == nm_add_domain.proposed.l3extDomP.attributes.name == 'l3_dom'
+ - cm_add_domain.current == cm_add_domain.previous == nm_add_domain.previous == []
+ - nm_add_domain.current.0.l3extDomP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_domain.current.0.l3extDomP.attributes.name == 'l3_dom'
+ - nm_add_domain.current.0.l3extDomP.attributes.dn == 'uni/l3dom-l3_dom'
+
+- name: Add L3 domain again (check_mode)
+ cisco.aci.aci_domain: *domain_present
+ check_mode: true
+ register: cm_add_domain_again
+
+- name: Add L3 domain again (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain_again
+
+- name: Verify L3 add_domain_again
+ assert:
+ that:
+ - cm_add_domain_again is not changed
+ - nm_add_domain_again is not changed
+
+- name: Update L3 domain with incorrect parameter vm_provider (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vm_provider
+
+- name: Update L3 domain with incorrect parameter vm_provider (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ ignore_errors: true
+ register: nm_incorrect_vm_provider
+
+- name: Update L3 domain with incorrect parameter encap_mode (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_encap_mode
+
+- name: Update L3 domain with incorrect parameter encap_mode (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ ignore_errors: true
+ register: nm_incorrect_encap_mode
+
+- name: Update L3 domain with incorrect parameter multicast_address (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_multicast_address
+
+- name: Update L3 domain with incorrect parameter multicast_address (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ ignore_errors: true
+ register: nm_incorrect_multicast_address
+
+- name: Update L3m domain with incorrect parameter vswitch (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vswitch
+
+- name: Update L3 domain with incorrect parameter vswitch (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ ignore_errors: true
+ register: nm_incorrect_vswitch
+
+- name: Verify incorrect parameter
+ assert:
+ that:
+ - cm_incorrect_vm_provider.msg == "Domain type 'l3dom' cannot have parameter 'vm_provider'"
+ - nm_incorrect_vm_provider.msg == "Domain type 'l3dom' cannot have parameter 'vm_provider'"
+ - cm_incorrect_encap_mode.msg == "Domain type 'l3dom' cannot have parameter 'encap_mode'"
+ - nm_incorrect_encap_mode.msg == "Domain type 'l3dom' cannot have parameter 'encap_mode'"
+ - cm_incorrect_multicast_address.msg == "Domain type 'l3dom' cannot have parameter 'multicast_address'"
+ - nm_incorrect_multicast_address.msg == "Domain type 'l3dom' cannot have parameter 'multicast_address'"
+ - cm_incorrect_vswitch.msg == "Domain type 'l3dom' cannot have parameter 'vswitch'"
+ - nm_incorrect_vswitch.msg == "Domain type 'l3dom' cannot have parameter 'vswitch'"
+
+
+# QUERY ALL DOMAINS
+- name: Query all L3 domains (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain_type: l3dom
+ state: query
+ check_mode: true
+ register: cm_query_all_domains
+
+- name: Query all L3 domains (normal mode)
+ cisco.aci.aci_domain: *domain_query
+ register: nm_query_all_domains
+
+- name: Verify query_all_domains
+ assert:
+ that:
+ - cm_query_all_domains is not changed
+ - nm_query_all_domains is not changed
+ - cm_query_all_domains == nm_query_all_domains
+ - nm_query_all_domains.current|length >= 1
+
+
+# QUERY A DOMAIN
+- name: Query our L3 domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l3_dom
+ check_mode: true
+ register: cm_query_domain
+
+- name: Query our L3 domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l3_dom
+ register: nm_query_domain
+
+- name: Verify L3 query_domain
+ assert:
+ that:
+ - cm_query_domain is not changed
+ - nm_query_domain is not changed
+ - cm_query_domain == nm_query_domain
+ - nm_query_domain.current.0.l3extDomP.attributes.dn == 'uni/l3dom-l3_dom'
+ - nm_query_domain.current.0.l3extDomP.attributes.name == 'l3_dom'
+
+
+# REMOVE DOMAIN
+- name: Remove L3 domain (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain
+
+- name: Remove L3 domain (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain
+
+- name: Verify L3 remove_domain
+ assert:
+ that:
+ - cm_remove_domain is changed
+ - nm_remove_domain is changed
+ - cm_remove_domain.current.0.l3extDomP.attributes.name == cm_remove_domain.previous.0.l3extDomP.attributes.name == nm_remove_domain.previous.0.l3extDomP.attributes.name == 'l3_dom'
+ - cm_remove_domain.current.0.l3extDomP.attributes.dn == cm_remove_domain.previous.0.l3extDomP.attributes.dn == nm_remove_domain.previous.0.l3extDomP.attributes.dn == 'uni/l3dom-l3_dom'
+ - nm_remove_domain.current == []
+
+- name: Remove L3 domain again (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain_again
+
+- name: Remove L3 domain again (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain_again
+
+- name: Verify L3 remove_domain_again
+ assert:
+ that:
+ - cm_remove_domain_again is not changed
+ - nm_remove_domain_again is not changed
+
+
+# QUERY NON-EXISTING DOMAIN
+- name: Query non-existing L3 domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l3_dom
+ check_mode: true
+ register: cm_query_non_domain
+
+- name: Query non-existing L3 domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: l3_dom
+ register: nm_query_non_domain
+
+- name: Verify L3 query_non_domain
+ assert:
+ that:
+ - cm_query_non_domain is not changed
+ - nm_query_non_domain is not changed
+ - cm_query_non_domain == nm_query_non_domain
+ - nm_query_non_domain.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml
new file mode 100644
index 000000000..be6c9712d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml
@@ -0,0 +1,24 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.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
+
+- include_tasks: phys.yml
+ when: phys is not defined or phys
+
+- include_tasks: l2dom.yml
+ when: l2dom is not defined or l2dom
+
+- include_tasks: l3dom.yml
+ when: l3dom is not defined or l3dom
+
+- include_tasks: fc.yml
+ when: fc is not defined or fc
+
+- include_tasks: vmm-vmware.yml
+ when: vmm_vmware is not defined or vmm_vmware
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml
new file mode 100644
index 000000000..39f87a6f0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml
@@ -0,0 +1,248 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove physical domain
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: phys_dom
+ domain_type: phys
+ state: absent
+
+
+# ADD DOMAIN
+- name: Add physical domain (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: phys_dom
+ domain_type: phys
+ state: present
+ check_mode: true
+ register: cm_add_domain
+
+- name: Add physical domain (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain
+
+- name: Verify physical add_domain
+ assert:
+ that:
+ - cm_add_domain is changed
+ - nm_add_domain is changed
+ - cm_add_domain.sent.physDomP.attributes.name == nm_add_domain.sent.physDomP.attributes.name == 'phys_dom'
+ - cm_add_domain.proposed.physDomP.attributes.name == nm_add_domain.proposed.physDomP.attributes.name == 'phys_dom'
+ - cm_add_domain.current == cm_add_domain.previous == nm_add_domain.previous == []
+ - nm_add_domain.current.0.physDomP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_domain.current.0.physDomP.attributes.name == 'phys_dom'
+ - nm_add_domain.current.0.physDomP.attributes.dn == 'uni/phys-phys_dom'
+
+- name: Add physical domain again (check_mode)
+ cisco.aci.aci_domain: *domain_present
+ check_mode: true
+ register: cm_add_domain_again
+
+- name: Add physical domain again (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain_again
+
+- name: Verify physical add_domain_again
+ assert:
+ that:
+ - cm_add_domain_again is not changed
+ - nm_add_domain_again is not changed
+
+- name: Update physical domain with incorrect parameter vm_provider (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vm_provider
+
+- name: Update physical domain with incorrect parameter vm_provider (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vm_provider: vmware
+ ignore_errors: true
+ register: nm_incorrect_vm_provider
+
+- name: Update physical domain with incorrect parameter encap_mode (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_encap_mode
+
+- name: Update physical domain with incorrect parameter encap_mode (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ encap_mode: vlan
+ ignore_errors: true
+ register: nm_incorrect_encap_mode
+
+- name: Update physical domain with incorrect parameter multicast_address (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_multicast_address
+
+- name: Update physical domain with incorrect parameter multicast_address (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ multicast_address: 10.10.10.0
+ ignore_errors: true
+ register: nm_incorrect_multicast_address
+
+- name: Update physical domain with incorrect parameter vswitch (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ check_mode: true
+ ignore_errors: true
+ register: cm_incorrect_vswitch
+
+- name: Update physical domain with incorrect parameter vswitch (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ vswitch: avs
+ ignore_errors: true
+ register: nm_incorrect_vswitch
+
+- name: Verify incorrect parameter
+ assert:
+ that:
+ - cm_incorrect_vm_provider.msg == "Domain type 'phys' cannot have parameter 'vm_provider'"
+ - nm_incorrect_vm_provider.msg == "Domain type 'phys' cannot have parameter 'vm_provider'"
+ - cm_incorrect_encap_mode.msg == "Domain type 'phys' cannot have parameter 'encap_mode'"
+ - nm_incorrect_encap_mode.msg == "Domain type 'phys' cannot have parameter 'encap_mode'"
+ - cm_incorrect_multicast_address.msg == "Domain type 'phys' cannot have parameter 'multicast_address'"
+ - nm_incorrect_multicast_address.msg == "Domain type 'phys' cannot have parameter 'multicast_address'"
+ - cm_incorrect_vswitch.msg == "Domain type 'phys' cannot have parameter 'vswitch'"
+ - nm_incorrect_vswitch.msg == "Domain type 'phys' cannot have parameter 'vswitch'"
+
+# QUERY ALL DOMAINS
+- name: Query all physical domains (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain_type: phys
+ state: query
+ check_mode: true
+ register: cm_query_all_domains
+
+- name: Query all physical domains (normal mode)
+ cisco.aci.aci_domain: *domain_query
+ register: nm_query_all_domains
+
+- name: Verify physical query_all_domains
+ assert:
+ that:
+ - cm_query_all_domains is not changed
+ - nm_query_all_domains is not changed
+ - cm_query_all_domains == nm_query_all_domains
+ - nm_query_all_domains.current|length >= 1
+
+
+# QUERY A DOMAIN
+- name: Query our physical domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: phys_dom
+ check_mode: true
+ register: cm_query_domain
+
+- name: Query our physical domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: phys_dom
+ register: nm_query_domain
+
+- name: Verify physical query_domain
+ assert:
+ that:
+ - cm_query_domain is not changed
+ - nm_query_domain is not changed
+ - cm_query_domain == nm_query_domain
+ - nm_query_domain.current.0.physDomP.attributes.dn == 'uni/phys-phys_dom'
+ - nm_query_domain.current.0.physDomP.attributes.name == 'phys_dom'
+
+
+# REMOVE DOMAIN
+- name: Remove physical domain (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain
+
+- name: Remove physical domain (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain
+
+- name: Verify physical remove_domain
+ assert:
+ that:
+ - cm_remove_domain is changed
+ - nm_remove_domain is changed
+ - cm_remove_domain.current.0.physDomP.attributes.name == cm_remove_domain.previous.0.physDomP.attributes.name == nm_remove_domain.previous.0.physDomP.attributes.name == 'phys_dom'
+ - cm_remove_domain.current.0.physDomP.attributes.dn == cm_remove_domain.previous.0.physDomP.attributes.dn == nm_remove_domain.previous.0.physDomP.attributes.dn == 'uni/phys-phys_dom'
+ - nm_remove_domain.current == []
+
+- name: Remove physical domain again (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain_again
+
+- name: Remove physical domain again (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain_again
+
+- name: Verify physical remove_domain_again
+ assert:
+ that:
+ - cm_remove_domain_again is not changed
+ - nm_remove_domain_again is not changed
+
+
+# QUERY NON-EXISTING DOMAIN
+- name: Query non-existing physical domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: phys_dom
+ check_mode: true
+ register: cm_query_non_domain
+
+- name: Query non-existing physical domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: phys_dom
+ register: nm_query_non_domain
+
+- name: Verify physical query_non_domain
+ assert:
+ that:
+ - cm_query_non_domain is not changed
+ - nm_query_non_domain is not changed
+ - cm_query_non_domain == nm_query_non_domain
+ - nm_query_non_domain.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml
new file mode 100644
index 000000000..03d82788c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml
@@ -0,0 +1,217 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# CLEAN ENVIRONMENT
+- name: Remove VMM domain
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: vmware
+ 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 skip execution for cloud sites
+ block:
+ # ADD DOMAIN
+ - name: Add VMM domain (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: vmware
+ access_mode: read-write
+ enable_vm_folder: true
+ state: present
+ check_mode: true
+ register: cm_add_domain
+
+ - name: Add VMM domain (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain
+
+ - name: Verify VMM add_domain
+ assert:
+ that:
+ - cm_add_domain is changed
+ - nm_add_domain is changed
+ - cm_add_domain.sent.vmmDomP.attributes.name == nm_add_domain.sent.vmmDomP.attributes.name == 'vmm_dom'
+ - cm_add_domain.proposed.vmmDomP.attributes.name == nm_add_domain.proposed.vmmDomP.attributes.name == 'vmm_dom'
+ - cm_add_domain.current == cm_add_domain.previous == nm_add_domain.previous == []
+ - nm_add_domain.current.0.vmmDomP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom'
+ - nm_add_domain.current.0.vmmDomP.attributes.name == 'vmm_dom'
+ - nm_add_domain.current.0.vmmDomP.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add VMM domain again (check_mode)
+ cisco.aci.aci_domain: *domain_present
+ check_mode: true
+ register: cm_add_domain_again
+
+ - name: Add VMM domain again (normal mode)
+ cisco.aci.aci_domain: *domain_present
+ register: nm_add_domain_again
+
+ - name: Verify VMM add_domain_again
+ assert:
+ that:
+ - cm_add_domain_again is not changed
+ - nm_add_domain_again is not changed
+
+ - name: Update VMM domain with tag collection and infra port groups (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ add_infra_pg: true
+ tag_collection: true
+ check_mode: true
+ register: cm_update_domain
+ when: version.current.0.topSystem.attributes.version is version('4.1', '>=')
+
+ - name: Update VMM domain with tag collection and infra port groups (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_present
+ add_infra_pg: true
+ tag_collection: true
+ register: nm_update_domain
+ when: version.current.0.topSystem.attributes.version is version('4.1', '>=')
+
+ - name: Verify update_domain
+ assert:
+ that:
+ - cm_update_domain is changed
+ - nm_update_domain is changed
+ - cm_update_domain.previous.0.vmmDomP.attributes.configInfraPg == nm_update_domain.previous.0.vmmDomP.attributes.configInfraPg == 'no'
+ - cm_update_domain.proposed.vmmDomP.attributes.configInfraPg == nm_update_domain.current.0.vmmDomP.attributes.configInfraPg == 'yes'
+ - cm_update_domain.previous.0.vmmDomP.attributes.enableTag == nm_update_domain.previous.0.vmmDomP.attributes.enableTag == 'no'
+ - cm_update_domain.proposed.vmmDomP.attributes.enableTag == nm_update_domain.current.0.vmmDomP.attributes.enableTag == 'yes'
+ when: version.current.0.topSystem.attributes.version is version('4.1', '>=')
+
+ # QUERY ALL DOMAINS
+ - name: Query all VMM domains (check_mode)
+ cisco.aci.aci_domain: &domain_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") }}'
+ domain_type: vmm
+ vm_provider: vmware
+ state: query
+ check_mode: true
+ register: cm_query_all_domains
+
+ - name: Query all VMM domains (normal mode)
+ cisco.aci.aci_domain: *domain_query
+ register: nm_query_all_domains
+
+ - name: Verify query_all_domains
+ assert:
+ that:
+ - cm_query_all_domains is not changed
+ - nm_query_all_domains is not changed
+ - cm_query_all_domains == nm_query_all_domains
+ - nm_query_all_domains.current|length >= 1
+
+
+ # QUERY A DOMAIN
+ - name: Query our VMM domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: vmm_dom
+ vm_provider: vmware
+ check_mode: true
+ register: cm_query_domain
+
+ - name: Query our VMM domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: vmm_dom
+ vm_provider: vmware
+ register: nm_query_domain
+
+ - name: Verify VMM query_domain
+ assert:
+ that:
+ - cm_query_domain is not changed
+ - nm_query_domain is not changed
+ - cm_query_domain == nm_query_domain
+ - nm_query_domain.current.0.vmmDomP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom'
+ - nm_query_domain.current.0.vmmDomP.attributes.name == 'vmm_dom'
+
+ # REMOVE DOMAIN
+ - name: Remove VMM domain (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain
+
+ - name: Remove VMM domain (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain
+
+ - name: Verify VMM remove_domain
+ assert:
+ that:
+ - cm_remove_domain is changed
+ - nm_remove_domain is changed
+ - cm_remove_domain.current == cm_remove_domain.previous == nm_remove_domain.previous
+ - nm_remove_domain.previous.0.vmmDomP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom'
+ - nm_remove_domain.previous.0.vmmDomP.attributes.name == 'vmm_dom'
+ - nm_remove_domain.current == []
+
+ - name: Remove VMM domain again (check_mode)
+ cisco.aci.aci_domain: *domain_absent
+ check_mode: true
+ register: cm_remove_domain_again
+
+ - name: Remove VMM domain again (normal mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain_again
+
+ - name: Verify VMM remove_domain_again
+ assert:
+ that:
+ - cm_remove_domain_again is not changed
+ - nm_remove_domain_again is not changed
+
+
+ # QUERY NON-EXISTING DOMAIN
+ - name: Query non-existing VMM domain (check_mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: vmm_dom
+ vm_provider: vmware
+ check_mode: true
+ register: cm_query_non_domain
+
+ - name: Query non-existing VMM domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *domain_query
+ domain: vmm_dom
+ vm_provider: vmware
+ register: nm_query_non_domain
+
+ - name: Verify VMM query_non_domain
+ assert:
+ that:
+ - cm_query_non_domain is not changed
+ - nm_query_non_domain is not changed
+ - cm_query_non_domain == nm_query_non_domain
+ - nm_query_non_domain.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml
new file mode 100644
index 000000000..f028e2c56
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml
@@ -0,0 +1,655 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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
+
+# Clean Environment
+- name: Remove domains
+ aci_domain:
+ <<: *aci_info
+ domain: '{{ item.name }}'
+ domain_type: '{{ item.type }}'
+ state: absent
+ loop:
+ - { name: phys_dom, type: phys }
+ - { name: fc_dom, type: fc }
+ - { name: l2_dom, type: l2dom }
+ - { name: l3_dom, type: l3dom }
+
+- name: Remove domains
+ aci_domain:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: '{{ item.name }}'
+ state: absent
+ loop:
+ - { name: vmware }
+ - { name: microsoft }
+ - { name: cloudfoundry }
+ - { name: openshift }
+ - { name: openstack }
+ - { name: redhat }
+ - { name: kubernetes }
+
+- 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
+ # Add
+ - name: Add physical domain
+ aci_domain:
+ <<: *aci_info
+ domain: phys_dom
+ domain_type: phys
+ state: present
+ register: phys_domain
+
+ - name: Add l2 domain
+ aci_domain:
+ <<: *aci_info
+ domain: l2_dom
+ domain_type: l2dom
+ state: present
+ register: l2_domain
+
+ - name: Add l3 domain
+ aci_domain:
+ <<: *aci_info
+ domain: l3_dom
+ domain_type: l3dom
+ state: present
+ register: l3_domain
+
+ - name: Add FC domain
+ aci_domain:
+ <<: *aci_info
+ domain: fc_dom
+ domain_type: fc
+ state: present
+ register: fc_domain
+
+ - name: Add vmm domain
+ aci_domain:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: vmware
+ state: present
+ register: vmm_domain
+
+ - name: Add domain to encap pool binding (phys, pool_type=vlan)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ state: present
+ register: phys_vlan
+
+ - name: Add domain to encap pool binding (fc, pool_type=vsan)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: fc_dom
+ domain_type: fc
+ pool: test_pool
+ pool_type: vsan
+ pool_allocation_mode: dynamic
+ state: present
+ register: fc_vsan
+
+ - name: Add domain to encap pool binding (domain_type=l2dom)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: l2_dom
+ domain_type: l2dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: static
+ state: present
+ register: l2dom
+
+ - name: Add domain to encap pool binding (domain_type=l3dom)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: l3_dom
+ domain_type: l3dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: static
+ state: present
+ register: l3dom
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=cloudfoundry)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: cloudfoundry
+ state: present
+ register: vmm_cloudfoundry
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=kubernetes)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: kubernetes
+ state: present
+ register: vmm_kubernetes
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=microsoft)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: microsoft
+ state: present
+ register: vmm_microsoft
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=openshift)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: openshift
+ state: present
+ register: vmm_openshift
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=openstack)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: openstack
+ state: present
+ register: vmm_openstack
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=redhat)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: redhat
+ state: present
+ register: vmm_redhat
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=vmware)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: vmware
+ state: present
+ register: vmm_vmware
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=vmware) again
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: vmware
+ state: present
+ register: vmm_vmware_idemp
+
+ - name: Add domain to encap pool binding (phys with vm_provider)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_type: vlan
+ vm_provider: vmware
+ pool_allocation_mode: dynamic
+ state: present
+ ignore_errors: true
+ register: phys_vlan_with_vmm
+
+ - name: Add domain to encap pool binding (phys, pool_type=vlan, no allocation mode)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_type: vlan
+ state: present
+ ignore_errors: true
+ register: phys_vlan_no_alloc
+
+ - name: Add domain to encap pool binding (domain_type=vmm, vm_provider=vmware, pool_type=vxlan)
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool: test_pool
+ pool_type: vxlan
+ pool_allocation_mode: dynamic
+ vm_provider: vmware
+ state: present
+ ignore_errors: true
+ register: vmm_vmware_vxlan
+
+ - name: Add domain to encap pool binding (phys, pool_type=vlan) missing domain_type
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: phys_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ state: present
+ ignore_errors: true
+ register: phys_missing_domain_type
+
+ - name: Add domain to encap pool binding (phys, pool_type=vlan) missing pool_type
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ state: present
+ ignore_errors: true
+ register: phys_missing_pool_type
+
+ - name: Verify add operation for All Sites
+ assert:
+ that:
+ - phys_vlan is changed
+ - fc_vsan is changed
+ - l2dom is changed
+ - l3dom is changed
+ - vmm_kubernetes is changed
+ - phys_vlan.current.0.physDomP.attributes.annotation == 'orchestrator:ansible'
+ - phys_vlan.current.0.physDomP.children.0.infraRsVlanNs.attributes.tDn =='uni/infra/vlanns-[test_pool]-dynamic'
+ - fc_vsan.current.0.fcDomP.children.0.fcRsVsanNs.attributes.tDn == 'uni/infra/vsanns-[test_pool]-dynamic'
+ - l2dom.current.0.l2extDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-static'
+ - l3dom.current.0.l3extDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-static'
+ - vmm_kubernetes.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - phys_vlan_with_vmm.msg is match("Domain type '[0-9a-zA-Z]*' cannot have a 'vm_provider'")
+ - vmm_vmware_vxlan.msg is match("vxlan pools do not support setting the allocation_mode; please remove this parameter from the task")
+ - phys_vlan_no_alloc.msg is match("ACI requires the 'pool_allocation_mode' for 'pool_type' of 'vlan' and 'vsan' when 'pool' is provided")
+ - phys_missing_pool_type.msg is match("missing required arguments{{':'}} pool_type")
+ - phys_missing_domain_type.msg is match("missing required arguments{{':'}} domain_type")
+
+ - name: Verify add operation for Non-Cloud Sites
+ assert:
+ that:
+ - vmm_cloudfoundry is changed
+ - vmm_openshift is changed
+ - vmm_openstack is changed
+ - vmm_redhat is changed
+ - vmm_vmware is changed
+ - vmm_vmware_idemp is not changed
+ - vmm_cloudfoundry.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - vmm_microsoft.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - vmm_openshift.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - vmm_openstack.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - vmm_redhat.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - vmm_vmware.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+
+ # QUERY
+ - name: Query all
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: phys
+ pool_type: vlan
+ state: query
+ register: query_all
+
+ - name: Query phys
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: phys_dom
+ domain_type: phys
+ pool_type: vlan
+ state: query
+ register: query_phys
+
+ - name: Query fc
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: fc_dom
+ domain_type: fc
+ pool_type: vsan
+ state: query
+ register: query_fc
+
+ - name: Query l2dom
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: l2_dom
+ domain_type: l2dom
+ pool_type: vlan
+ state: query
+ register: query_l2dom
+
+ - name: Query l3dom
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: l3_dom
+ domain_type: l3dom
+ pool_type: vlan
+ state: query
+ register: query_l3dom
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: microsoft
+ state: query
+ register: query_vmm_microsoft
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: cloudfoundry
+ state: query
+ register: query_vmm_cloudfoundry
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: kubernetes
+ state: query
+ register: query_vmm_kubernetes
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: openshift
+ state: query
+ register: query_vmm_openshift
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: openstack
+ state: query
+ register: query_vmm_openstack
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: redhat
+ state: query
+ register: query_vmm_redhat
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: vmware
+ state: query
+ register: query_vmm_vmware
+
+ - name: Query vmm
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ pool_type: vlan
+ vm_provider: vmware
+ state: query
+ register: query_vmm_vmware
+
+ - name: Verify Query for Non-Cloud sites
+ assert:
+ that:
+ - query_all | length >=1
+ - query_phys.current.0.physDomP.children.0.infraRsVlanNs.attributes.tDn =='uni/infra/vlanns-[test_pool]-dynamic'
+ - query_fc.current.0.fcDomP.children.0.fcRsVsanNs.attributes.tDn == 'uni/infra/vsanns-[test_pool]-dynamic'
+ - query_l2dom.current.0.l2extDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-static'
+ - query_l3dom.current.0.l3extDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-static'
+ - query_vmm_kubernetes.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+
+
+ - name: Verify Query for Cloud sites
+ assert:
+ that:
+ - query_vmm_cloudfoundry.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - query_vmm_microsoft.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - query_vmm_openshift.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - query_vmm_openstack.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - query_vmm_redhat.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - query_vmm_vmware.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+
+ # REMOVE
+ - name: Remove phys
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: phys
+ domain: phys_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ state: absent
+ register: remove_phys
+
+ - name: Remove fc
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: fc
+ domain: fc_dom
+ pool: test_pool
+ pool_type: vsan
+ pool_allocation_mode: dynamic
+ state: absent
+ register: remove_fc
+
+ - name: Remove l2dom
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: l2dom
+ domain: l2_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: static
+ state: absent
+ register: remove_l2dom
+
+ - name: Remove l3dom
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: l3dom
+ domain: l3_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: static
+ state: absent
+ register: remove_l3dom
+
+ - name: Remove vmm cloudfoundry
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: vmm
+ domain: vmm_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: cloudfoundry
+ state: absent
+ register: remove_vmm_cloudfoundry
+
+ - name: Remove vmm redhat kubernetes
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: vmm
+ domain: vmm_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: kubernetes
+ state: absent
+ register: remove_vmm_kubernetes
+
+ - name: Remove vmm microsoft
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: vmm
+ domain: vmm_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: microsoft
+ state: absent
+ register: remove_vmm_microsoft
+
+ - name: Remove vmm redhat
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: vmm
+ domain: vmm_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: redhat
+ state: absent
+ register: remove_vmm_redhat
+
+ - name: Remove vmm openstack
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: vmm
+ domain: vmm_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: openstack
+ state: absent
+ register: remove_vmm_openstack
+
+ - name: Remove vmm openshift
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: vmm
+ domain: vmm_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: openshift
+ state: absent
+ register: remove_vmm_openshift
+
+ - name: Remove vmm vmware
+ aci_domain_to_encap_pool:
+ <<: *aci_info
+ domain_type: vmm
+ domain: vmm_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ vm_provider: vmware
+ state: absent
+ register: remove_vmm_vmware
+
+ - name: Verify Remove for All Sites
+ assert:
+ that:
+ - remove_phys.previous.0.physDomP.children.0.infraRsVlanNs.attributes.tDn =='uni/infra/vlanns-[test_pool]-dynamic'
+ - remove_fc.previous.0.fcDomP.children.0.fcRsVsanNs.attributes.tDn == 'uni/infra/vsanns-[test_pool]-dynamic'
+ - remove_l2dom.previous.0.l2extDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-static'
+ - remove_l3dom.previous.0.l3extDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-static'
+ - remove_vmm_kubernetes.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+
+ - name: Verify Remove for Non-Cloud Sites
+ assert:
+ that:
+ - remove_vmm_cloudfoundry.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - remove_vmm_microsoft.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - remove_vmm_openshift.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - remove_vmm_openstack.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - remove_vmm_redhat.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - remove_vmm_vmware.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+
+ # Clean Environment Again
+ - name: Remove domains
+ aci_domain:
+ <<: *aci_info
+ domain: '{{ item.name }}'
+ domain_type: '{{ item.type }}'
+ state: absent
+ loop:
+ - { name: phys_dom, type: phys }
+ - { name: fc_dom, type: fc }
+ - { name: l2_dom, type: l2dom }
+ - { name: l3_dom, type: l3dom }
+
+ - name: Remove domains
+ aci_domain:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: '{{ item.name }}'
+ state: absent
+ loop:
+ - { name: vmware }
+ - { name: microsoft }
+ - { name: cloudfoundry }
+ - { name: openshift }
+ - { name: openstack }
+ - { name: redhat }
+ - { name: kubernetes } \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..8c31fd4cc
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml
@@ -0,0 +1,228 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- 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: 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") }}'
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ state: absent
+
+ - name: Remove 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") }}'
+ domain: phys_dom
+ domain_type: phys
+ 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") }}'
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ description: Test VLAN pool
+ state: present
+
+
+ # 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") }}'
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ state: present
+ check_mode: true
+ register: cm_add_binding
+
+ - name: Add domain to VLAN pool binding (normal mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_present
+ register: nm_add_binding
+
+ - name: Verify add_binding
+ assert:
+ that:
+ - cm_add_binding is changed
+ - nm_add_binding is changed
+ - cm_add_binding.sent.physDomP.attributes.name == nm_add_binding.sent.physDomP.attributes.name == 'phys_dom'
+ - cm_add_binding.sent.physDomP.children.0.infraRsVlanNs.attributes.tDn == nm_add_binding.sent.physDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - cm_add_binding.proposed.physDomP.attributes.name == nm_add_binding.proposed.physDomP.attributes.name == 'phys_dom'
+ - cm_add_binding.proposed.physDomP.children.0.infraRsVlanNs.attributes.tDn == nm_add_binding.proposed.physDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - cm_add_binding.current == cm_add_binding.previous == nm_add_binding.previous == []
+ - nm_add_binding.current.0.physDomP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_binding.current.0.physDomP.attributes.name == 'phys_dom'
+ - nm_add_binding.current.0.physDomP.attributes.dn == 'uni/phys-phys_dom'
+ - nm_add_binding.current.0.physDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+
+ - name: Add domain to VLAN pool binding again (check_mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_present
+ check_mode: true
+ register: cm_add_binding_again
+
+ - name: Add domain to VLAN pool binding again (normal mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_present
+ register: nm_add_binding_again
+
+ - name: Verify add_binding_again
+ assert:
+ that:
+ - cm_add_binding_again is not changed
+ - nm_add_binding_again is not changed
+
+
+ # 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") }}'
+ domain_type: phys
+ pool_allocation_mode: dynamic
+ state: query
+ check_mode: true
+ register: cm_query_all_bindings
+
+ - name: Query all domain to VLAN pool bindings (normal mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_query
+ register: nm_query_all_bindings
+
+ - name: Verify query_all_bindings
+ assert:
+ that:
+ - cm_query_all_bindings is not changed
+ - nm_query_all_bindings is not changed
+ - cm_query_all_bindings == nm_query_all_bindings
+ - nm_query_all_bindings.current|length >= 1
+
+
+ # QUERY A BINDING
+ - name: Query our domain to VLAN pool binding (check_mode)
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_query
+ domain: phys_dom
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ check_mode: true
+ register: cm_query_binding
+
+ - name: Query our domain to VLAN pool binding (normal mode)
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_query
+ domain: phys_dom
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ register: nm_query_binding
+
+ - name: Verify query_binding
+ assert:
+ that:
+ - cm_query_binding is not changed
+ - nm_query_binding is not changed
+ - cm_query_binding == nm_query_binding
+ - nm_query_binding.current.0.physDomP.attributes.dn == 'uni/phys-phys_dom'
+ - nm_query_binding.current.0.physDomP.attributes.name == 'phys_dom'
+ - nm_query_binding.current.0.physDomP.children.0.infraRsVlanNs.attributes.tCl == 'fvnsVlanInstP'
+ - nm_query_binding.current.0.physDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+
+
+ # REMOVE BINDING
+ - name: Remove domain to VLAN pool binding (check_mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_absent
+ check_mode: true
+ register: cm_remove_binding
+
+ - name: Remove domain to VLAN pool binding (normal mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_absent
+ register: nm_remove_binding
+
+ - name: Verify remove_binding
+ assert:
+ that:
+ - cm_remove_binding is changed
+ - nm_remove_binding is changed
+ - cm_remove_binding.current.0.physDomP.attributes.dn == cm_remove_binding.previous.0.physDomP.attributes.dn == nm_remove_binding.previous.0.physDomP.attributes.dn == 'uni/phys-phys_dom'
+ - cm_remove_binding.current.0.physDomP.attributes.name == cm_remove_binding.previous.0.physDomP.attributes.name == nm_remove_binding.previous.0.physDomP.attributes.name == 'phys_dom'
+ - cm_remove_binding.current.0.physDomP.children.0.infraRsVlanNs.attributes.tDn == cm_remove_binding.previous.0.physDomP.children.0.infraRsVlanNs.attributes.tDn == nm_remove_binding.previous.0.physDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - nm_remove_binding.current == []
+
+ - name: Remove domain to VLAN pool binding again (check_mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_absent
+ check_mode: true
+ register: cm_remove_binding_again
+
+ - name: Remove domain to VLAN pool binding again (normal mode)
+ cisco.aci.aci_domain_to_vlan_pool: *binding_absent
+ register: nm_remove_binding_again
+
+ - name: Verify remove_binding_again
+ assert:
+ that:
+ - cm_remove_binding_again is not changed
+ - nm_remove_binding_again is not changed
+
+
+ # QUERY NON-EXISTING BINDING
+ - name: Query non-existing domain to VLAN pool binding (check_mode)
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_query
+ domain: phys_dom
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ check_mode: true
+ register: cm_query_non_binding
+
+ - name: Query non-existing domain to VLAN pool binding (normal mode)
+ cisco.aci.aci_domain_to_vlan_pool:
+ <<: *binding_query
+ domain: phys_dom
+ pool: test_pool
+ pool_allocation_mode: dynamic
+ register: nm_query_non_binding
+
+ - name: Verify query_non_binding
+ assert:
+ that:
+ - cm_query_non_binding is not changed
+ - nm_query_non_binding is not changed
+ - cm_query_non_binding == nm_query_non_binding
+ - nm_query_non_binding.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml
new file mode 100644
index 000000000..f0e61a7ef
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml
@@ -0,0 +1,24 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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
+ block: # block specifies execution of tasks within, based on conditions
+ - include_tasks: vlan.yml
+ when: vlan is not defined or vlan
+
+ - include_tasks: vxlan.yml
+ when: vxlan is not defined or vxlan
+
+ - include_tasks: vsan.yml
+ when: vsan is not defined or vsan
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml
new file mode 100644
index 000000000..1354c149a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml
@@ -0,0 +1,275 @@
+---
+- name: ensure vlan pool does not exist for tests to kick off
+ cisco.aci.aci_encap_pool: &aci_pool_absent_static
+ 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: absent
+ pool: anstest
+ pool_type: vlan
+ pool_allocation_mode: static
+
+- name: ensure vlan pool does not exist for tests to kick off
+ cisco.aci.aci_encap_pool: &aci_pool_absent_dynamic
+ <<: *aci_pool_absent_static
+ pool_allocation_mode: dynamic
+
+- name: create static vlan pool - check mode works
+ cisco.aci.aci_encap_pool: &aci_pool_present_static
+ <<: *aci_pool_absent_static
+ state: present
+ descr: Ansible Test
+ check_mode: true
+ register: create_check_mode
+
+- name: assertion test - present
+ assert:
+ that:
+ - create_check_mode is changed
+ - create_check_mode.sent.fvnsVlanInstP.attributes.allocMode == 'static'
+ - create_check_mode.sent.fvnsVlanInstP.attributes.descr == 'Ansible Test'
+ - create_check_mode.sent.fvnsVlanInstP.attributes.name == 'anstest'
+
+- name: create static vlan pool - creation works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_static
+ register: create_static
+
+- name: assertion test - present
+ assert:
+ that:
+ - create_static is changed
+ - create_static.previous == []
+ - create_static.sent == create_check_mode.sent
+
+- name: create dynamic vlan pool - creation works
+ cisco.aci.aci_encap_pool: &aci_pool_present_dynamic
+ <<: *aci_pool_absent_dynamic
+ state: present
+ descr: Ansible Test
+ register: create_dynamic
+
+- name: assertion test - present
+ assert:
+ that:
+ - create_dynamic is changed
+ - create_dynamic.previous == []
+ - create_dynamic.sent.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - create_dynamic.sent.fvnsVlanInstP.attributes.descr == 'Ansible Test'
+ - create_dynamic.sent.fvnsVlanInstP.attributes.name == 'anstest'
+ - create_dynamic.current.0.fvnsVlanInstP.attributes.annotation == 'orchestrator:ansible'
+
+- name: create static vlan pool again - idempotency works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_static
+ register: idempotent_static
+
+- name: assertion test - present
+ assert:
+ that:
+ - idempotent_static is not changed
+ - idempotent_static.previous.0.fvnsVlanInstP.attributes.allocMode == 'static'
+ - idempotent_static.previous.0.fvnsVlanInstP.attributes.descr == 'Ansible Test'
+ - idempotent_static.previous.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-static'
+ - idempotent_static.previous.0.fvnsVlanInstP.attributes.name == 'anstest'
+ - idempotent_static.sent == {}
+
+- name: create dynamic vlan pool again - idempotency works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_dynamic
+ register: idempotent_dynamic
+
+- name: assertion test - present
+ assert:
+ that:
+ - idempotent_dynamic is not changed
+ - idempotent_dynamic.previous.0.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - idempotent_dynamic.previous.0.fvnsVlanInstP.attributes.descr == 'Ansible Test'
+ - idempotent_dynamic.previous.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-dynamic'
+ - idempotent_dynamic.previous.0.fvnsVlanInstP.attributes.name == 'anstest'
+ - idempotent_dynamic.sent == {}
+
+- name: update static vlan pool - update works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_static
+ descr: Ansible Test Change
+ register: update_static
+
+- name: assertion test - present
+ assert:
+ that:
+ - update_static is changed
+ - update_static.sent.fvnsVlanInstP.attributes.descr == 'Ansible Test Change'
+
+- name: update dynamic vlan pool - update works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_dynamic
+ descr: Ansible Test Change
+ register: update_dynamic
+
+- name: assertion test - present
+ assert:
+ that:
+ - update_dynamic is changed
+ - update_dynamic.sent.fvnsVlanInstP.attributes.descr == 'Ansible Test Change'
+
+- name: missing param - failure message works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_dynamic
+ pool_allocation_mode: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: vlan_alloc_fail
+
+- name: assertion test - present
+ assert:
+ that:
+ - vlan_alloc_fail is failed
+ - "vlan_alloc_fail.msg == 'ACI requires parameter \\'pool_allocation_mode\\' for \\'pool_type\\' of \\'vlan\\' and \\'vsan\\' when parameter \\'pool\\' is provided'"
+
+- name: missing param - failure message works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_dynamic
+ pool: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: vlan_pool_fail
+
+- name: assertion test - present
+ assert:
+ that:
+ - vlan_pool_fail is failed
+ - 'vlan_pool_fail.msg == "state is present but all of the following are missing: pool"'
+
+- name: missing param - failure message works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_present_dynamic
+ pool_type: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: vlan_pool_type_fail
+
+- name: assertion test - present
+ assert:
+ that:
+ - vlan_pool_type_fail is failed
+ - 'vlan_pool_type_fail.msg == "missing required arguments: pool_type"'
+
+- name: get all vlan pools - get class works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_static
+ state: query
+ pool: "{{ fake_var | default(omit) }}"
+ pool_allocation_mode: "{{ fake_var | default(omit) }}"
+ register: get_all_pools
+
+- name: assertion test - query
+ assert:
+ that:
+ - get_all_pools is not changed
+ - get_all_pools.method == "GET"
+ - get_all_pools.current | length > 1
+
+- name: get created static vlan pool - get mo works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_static
+ state: query
+ register: get_static_pool
+
+- name: assertion test - query
+ assert:
+ that:
+ - get_static_pool is not changed
+ - get_static_pool.method == "GET"
+ - get_static_pool.current | length == 1
+ - get_static_pool.current.0.fvnsVlanInstP.attributes.allocMode == "static"
+ - get_static_pool.current.0.fvnsVlanInstP.attributes.name == "anstest"
+
+- name: get created dynamic vlan pool - get mo works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_dynamic
+ state: query
+ register: get_dynamic_pool
+
+- name: assertion test - query
+ assert:
+ that:
+ - get_dynamic_pool is not changed
+ - get_dynamic_pool.method == "GET"
+ - get_dynamic_pool.current | length == 1
+ - get_dynamic_pool.current.0.fvnsVlanInstP.attributes.allocMode == "dynamic"
+ - get_dynamic_pool.current.0.fvnsVlanInstP.attributes.name == "anstest"
+
+- name: get created dynamic vlan pool - get mo works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_dynamic
+ state: query
+ pool_type: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: vlan_query_pool_type_fail
+
+- name: assertion test - query
+ assert:
+ that:
+ - vlan_query_pool_type_fail is failed
+ - 'vlan_query_pool_type_fail.msg == "missing required arguments: pool_type"'
+
+- name: delete static vlan pool - deletion works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_static
+ register: delete_static
+
+- name: assertion test - absent
+ assert:
+ that:
+ - delete_static is changed
+ - delete_static.method == "DELETE"
+ - delete_static.previous.0.fvnsVlanInstP.attributes.allocMode == "static"
+ - delete_static.previous.0.fvnsVlanInstP.attributes.name == "anstest"
+
+- name: delete dynamic vlan pool - check mode works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_dynamic
+ check_mode: true
+ register: delete_check_mode
+
+- name: assertion test - absent
+ assert:
+ that:
+ - delete_check_mode is changed
+
+- name: delete dynamic vlan pool - deletion works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_dynamic
+ register: delete_dynamic
+
+- name: assertion test - absent
+ assert:
+ that:
+ - delete_dynamic is changed
+ - delete_dynamic.method == "DELETE"
+ - delete_dynamic.previous.0.fvnsVlanInstP.attributes.allocMode == "dynamic"
+ - delete_dynamic.previous.0.fvnsVlanInstP.attributes.name == "anstest"
+
+- name: delete static vlan pool again - idempotency works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_static
+ register: idempotent_delete_static
+
+- name: assertion test - absent
+ assert:
+ that:
+ - idempotent_delete_static is not changed
+ - idempotent_delete_static.previous == []
+
+- name: delete dynamic vlan pool again - idempotency works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_pool_absent_dynamic
+ register: idempotent_delete_dynamic
+
+- name: assertion test - absent
+ assert:
+ that:
+ - idempotent_delete_dynamic is not changed
+ - idempotent_delete_dynamic.previous == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vsan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vsan.yml
new file mode 100644
index 000000000..846818731
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vsan.yml
@@ -0,0 +1,16 @@
+---
+- name: ensure vlan pool does not exist for tests to kick off
+ cisco.aci.aci_encap_pool: &aci_pool_absent_static
+ 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") }}'
+ pool: anstest
+ pool_type: vsan
+ pool_allocation_mode: static
+ state: absent
+
+# FIXME: Add Test to this integration \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml
new file mode 100644
index 000000000..6467af376
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml
@@ -0,0 +1,179 @@
+---
+- name: ensure vxlan pool anstest does not exist for tests to kick off
+ cisco.aci.aci_encap_pool: &aci_vxlan_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
+ state: absent
+ pool: anstest
+ pool_type: vxlan
+
+- name: ensure vxlan pool anstest_2 does not exist for tests to kick off
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_absent
+ pool: anstest_2
+
+- name: ensure vxlan pool anstest_3 does not exist for tests to kick off
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_absent
+ pool: anstest_3
+
+- name: create vxlan pool - check mode works
+ cisco.aci.aci_encap_pool: &aci_vxlan_present
+ <<: *aci_vxlan_absent
+ state: present
+ descr: Ansible Test
+ check_mode: true
+ register: create_vxlan_check_mode
+
+- name: assertion test - present
+ assert:
+ that:
+ - create_vxlan_check_mode is changed
+ - create_vxlan_check_mode.sent.fvnsVxlanInstP.attributes.descr == 'Ansible Test'
+ - create_vxlan_check_mode.sent.fvnsVxlanInstP.attributes.name == 'anstest'
+
+- name: create vxlan pool - creation works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_present
+ register: create_vxlan
+
+- name: assertion test - present
+ assert:
+ that:
+ - create_vxlan is changed
+ - create_vxlan.previous == []
+ - create_vxlan.sent == create_vxlan_check_mode.sent
+ - create_vxlan.current.0.fvnsVxlanInstP.attributes.annotation == 'orchestrator:ansible'
+
+- name: create vxlan pool again - idempotency works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_present
+ register: idempotent_vxlan
+
+- name: assertion test - present
+ assert:
+ that:
+ - idempotent_vxlan is not changed
+ - idempotent_vxlan.previous.0.fvnsVxlanInstP.attributes.name == 'anstest'
+ - idempotent_vxlan.sent == {}
+
+- name: update vxlan pool - update works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_present
+ descr: Ansible Test Change
+ register: update_vxlan
+
+- name: assertion test - present
+ assert:
+ that:
+ - update_vxlan is changed
+ - update_vxlan.sent.fvnsVxlanInstP.attributes.descr == 'Ansible Test Change'
+
+- name: create vxlan pool - used for query
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_present
+ name: anstest_2
+ register: create_vxlan_2
+
+- name: assertion test - present
+ assert:
+ that:
+ - create_vxlan_2 is changed
+
+- name: create vxlan pool with pool allocation mode - failure message works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_present
+ name: anstest_3
+ pool_allocation_mode: dynamic
+ ignore_errors: true
+ register: create_vxlan_alloc_mode
+
+- name: assertion test - present
+ assert:
+ that:
+ - create_vxlan_alloc_mode is failed
+ - "create_vxlan_alloc_mode.msg == 'vxlan pools do not support setting the \\'pool_allocation_mode\\'; please remove this parameter from the task'"
+
+- name: get vxlan pool - get object works
+ cisco.aci.aci_encap_pool: &aci_vxlan_query
+ <<: *aci_vxlan_present
+ state: query
+ register: query_vxlan
+
+- name: assertion test - query
+ assert:
+ that:
+ - query_vxlan is not changed
+ - query_vxlan.current | length == 1
+ - '"infra/vxlanns-anstest.json" in query_vxlan.url'
+
+- name: get created static vlan pool - get class works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_query
+ pool: "{{ fake_var | default(omit) }}"
+ register: query_vxlan_all
+
+- name: assertion test - query
+ assert:
+ that:
+ - query_vxlan_all is not changed
+ - query_vxlan_all.current | length > 1
+ - '"class/fvnsVxlanInstP.json" in query_vxlan_all.url'
+
+- name: delete vxlan pool - check mode works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_absent
+ check_mode: true
+ register: delete_vxlan_check_mode
+
+- name: assertion test - absent
+ assert:
+ that:
+ - delete_vxlan_check_mode is changed
+ - delete_vxlan_check_mode.previous != []
+
+- name: delete vxlan pool - deletion works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_absent
+ register: delete_vxlan
+
+- name: assertion test - absent
+ assert:
+ that:
+ - delete_vxlan is changed
+ - delete_vxlan.previous == delete_vxlan_check_mode.previous
+ - delete_vxlan.previous.0.fvnsVxlanInstP.attributes.name == "anstest"
+
+- name: delete vxlan pool again - idempotency works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_absent
+ register: delete_vxlan_idempotent
+
+- name: missing param - failure message works
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_absent
+ pool: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: delete_vxlan_pool_fail
+
+- name: assertion test - absent
+ assert:
+ that:
+ - delete_vxlan_idempotent is not changed
+ - delete_vxlan_idempotent.previous == []
+
+- name: delete vxlan pool - cleanup
+ cisco.aci.aci_encap_pool:
+ <<: *aci_vxlan_absent
+ pool: anstest_2
+
+- name: assertion test - absent
+ assert:
+ that:
+ - delete_vxlan_pool_fail is failed
+ - 'delete_vxlan_pool_fail.msg == "state is absent but all of the following are missing: pool"'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml
new file mode 100644
index 000000000..005628c5d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml
@@ -0,0 +1,24 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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
+ block: # block specifies execution of tasks within, based on conditions
+ - include_tasks: vlan.yml
+ when: "vlan is not defined or (vlan is defined and vlan == 'True')"
+
+ - include_tasks: vxlan.yml
+ when: "vxlan is not defined or (vxlan is defined and vxlan == 'True')"
+
+ - include_tasks: vsan.yml
+ when: "vsan is not defined or (vsan is defined and vsan == 'True')"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml
new file mode 100644
index 000000000..6af58bf5d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml
@@ -0,0 +1,388 @@
+- name: ensure vlan pool exists for tests to kick off
+ cisco.aci.aci_encap_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") }}'
+ state: absent
+ pool: anstest
+ pool_type: vlan
+ allocation_mode: static
+ description: Ansible Test
+
+- name: ensure vlan pool exists for tests to kick off
+ 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: debug
+ state: present
+ pool: anstest
+ pool_type: vlan
+ allocation_mode: static
+ description: Ansible Test
+ register: pool_present
+
+- name: create vlan pool range - check mode works
+ cisco.aci.aci_encap_pool_range: &aci_range_present
+ <<: *aci_pool_present
+ range_name: anstest
+ range_start: 20
+ range_end: 40
+ pool: anstest
+ pool_allocation_mode: static
+ allocation_mode: inherit
+ description: Ansible Test
+ check_mode: true
+ register: range_present_check_mode
+
+- name: present assertions
+ assert:
+ that:
+ - range_present_check_mode is changed
+ - range_present_check_mode.sent.fvnsEncapBlk.attributes.allocMode == 'inherit'
+ - range_present_check_mode.sent.fvnsEncapBlk.attributes.descr == 'Ansible Test'
+ - range_present_check_mode.sent.fvnsEncapBlk.attributes.name == 'anstest'
+ - range_present_check_mode.sent.fvnsEncapBlk.attributes.from == 'vlan-20'
+ - range_present_check_mode.sent.fvnsEncapBlk.attributes.to == 'vlan-40'
+
+- name: create vlan pool range - creation works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ register: range_present
+
+- name: present assertions
+ assert:
+ that:
+ - range_present is changed
+ - range_present.previous == []
+ - range_present.sent == range_present_check_mode.sent
+ - range_present.sent == range_present.proposed
+ - range_present.current.0.fvnsEncapBlk.attributes.annotation == 'orchestrator:ansible'
+
+- name: create vlan pool range - idempotency works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ register: range_present_idempotent
+
+- name: present assertions
+ assert:
+ that:
+ - range_present_idempotent is not changed
+ - range_present_idempotent.previous.0.fvnsEncapBlk.attributes.name == "anstest"
+
+- name: update vlan pool range - update works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ description: Ansible Test Update
+ allocation_mode: inherit
+ register: range_present_update
+
+- name: present assertions
+ assert:
+ that:
+ - range_present_update is changed
+ - range_present_update.previous != []
+ - range_present_update.sent != range_present.sent
+
+- name: create vlan pool range - used for query
+ cisco.aci.aci_encap_pool_range: &aci_range_present_2
+ <<: *aci_range_present
+ range_name: anstest_2
+ range_start: 50
+ range_end: 55
+ register: range_present_2
+
+- name: present assertions
+ assert:
+ that:
+ - range_present_2 is changed
+ - range_present_2.previous == []
+
+- name: invalid range_start - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ range_start: 0
+ ignore_errors: true
+ register: range_start_low
+
+- name: present assertions
+ assert:
+ that:
+ - range_start_low is failed
+ - range_start_low.msg == 'vlan pools must have "range_start" and "range_end" values between 1 and 4094'
+
+- name: invalid range_start - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ range_start: 4096
+ ignore_errors: true
+ register: range_start_high
+
+- name: present assertions
+ assert:
+ that:
+ - range_start_high is failed
+ - range_start_high.msg == 'vlan pools must have "range_start" and "range_end" values between 1 and 4094'
+
+- name: invalid range_end - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ range_end: 0
+ ignore_errors: true
+ register: range_end_low
+
+- name: present assertions
+ assert:
+ that:
+ - range_end_low is failed
+ - range_end_low.msg == 'vlan pools must have "range_start" and "range_end" values between 1 and 4094'
+
+- name: invalid range_end - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ range_end: 4096
+ ignore_errors: true
+ register: range_end_high
+
+- name: present assertions
+ assert:
+ that:
+ - range_end_high is failed
+ - range_end_high.msg == 'vlan pools must have "range_start" and "range_end" values between 1 and 4094'
+
+- name: range start higher than range end - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ range_start: 1000
+ ignore_errors: true
+ register: range_start_end
+
+- name: present assertions
+ assert:
+ that:
+ - range_start_end is failed
+ - range_start_end.msg == 'The "range_start" must be less than or equal to the "range_end"'
+
+- name: missing required param - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ pool_type: '{{ omit }}'
+ ignore_errors: true
+ register: range_present_pool_type
+
+- name: present assertions
+ assert:
+ that:
+ - range_present_pool_type is failed
+ - "range_present_pool_type.msg == 'missing required arguments: pool_type'"
+
+- name: missing required param - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_pool_present
+ ignore_errors: true
+ register: range_present_missing_param
+
+- name: present assertions
+ assert:
+ that:
+ - range_present_missing_param is failed
+ - "range_present_missing_param.msg == 'state is present but all of the following are missing: range_end, range_start'"
+
+- name: missing required param - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ pool_allocation_mode: '{{ omit }}'
+ ignore_errors: true
+ register: range_present_allocation
+
+- name: present assertions
+ assert:
+ that:
+ - range_present_allocation is failed
+ - range_present_allocation.msg == 'ACI requires the "pool_allocation_mode" for "pool_type" of "vlan" and "vsan" when the "pool" is provided'
+
+- name: query specific vlan pool range
+ cisco.aci.aci_encap_pool_range: &aci_range_query
+ <<: *aci_range_present
+ state: query
+ register: range_query
+
+- name: query assertions
+ assert:
+ that:
+ - range_query is not changed
+ - range_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json")
+ - range_query.current | length == 1
+ - range_query.current.0.fvnsEncapBlk.attributes.name == "anstest"
+
+- name: query vlan pool range - from, to, and name are filtered
+ cisco.aci.aci_encap_pool_range: &aci_range_query_filter
+ <<: *aci_range_query
+ pool: '{{ omit }}'
+ register: range_query_from_to_name
+
+- name: query assertions
+ assert:
+ that:
+ - range_query_from_to_name is not changed
+ - range_query_from_to_name.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.from,\"vlan-20\")" in range_query_from_to_name.filter_string'
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in range_query_from_to_name.filter_string'
+ - '"eq(fvnsEncapBlk.to,\"vlan-40\")" in range_query_from_to_name.filter_string'
+ - range_query_from_to_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+ - range_query_from_to_name.current.0.fvnsEncapBlk.attributes.from == "vlan-20"
+ - range_query_from_to_name.current.0.fvnsEncapBlk.attributes.to == "vlan-40"
+
+- name: query vlan pool range - from and name are filtered
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_query_filter
+ range_end: '{{ omit }}'
+ register: range_query_from_name
+
+- name: query assertions
+ assert:
+ that:
+ - range_query_from_name is not changed
+ - range_query_from_name.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.from,\"vlan-20\")" in range_query_from_name.filter_string'
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in range_query_from_name.filter_string'
+ - range_query_from_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+ - range_query_from_name.current.0.fvnsEncapBlk.attributes.from == "vlan-20"
+
+- name: query vlan pool range - to and name are filtered
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_query_filter
+ range_start: '{{ omit }}'
+ register: range_query_to_name
+
+- name: query assertions
+ assert:
+ that:
+ - range_query_to_name is not changed
+ - range_query_to_name.url.endswith('class/fvnsEncapBlk.json')
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in range_query_to_name.filter_string'
+ - '"eq(fvnsEncapBlk.to,\"vlan-40\")" in range_query_to_name.filter_string'
+ - range_query_to_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+ - range_query_to_name.current.0.fvnsEncapBlk.attributes.to == "vlan-40"
+
+- name: query vlan pool range - name is filtered
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_query_filter
+ range_start: '{{ omit }}'
+ range_end: '{{ omit }}'
+ register: range_query_name
+
+- name: query assertions
+ assert:
+ that:
+ - range_query_name is not changed
+ - range_query_name.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in range_query_name.filter_string'
+ - range_query_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+
+- name: query vlan pool range - from and to are filtered
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_query_filter
+ range_name: '{{ omit }}'
+ register: range_query_from_to
+
+- name: query assertions
+ assert:
+ that:
+ - range_query_from_to is not changed
+ - range_query_from_to.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.from,\"vlan-20\")" in range_query_from_to.filter_string'
+ - '"eq(fvnsEncapBlk.to,\"vlan-40\")" in range_query_from_to.filter_string'
+ - range_query_from_to.current.0.fvnsEncapBlk.attributes.from == "vlan-20"
+ - range_query_from_to.current.0.fvnsEncapBlk.attributes.to == "vlan-40"
+
+- name: query all ranges in a vlan pool
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_pool_present
+ state: query
+ pool_allocation_mode: static
+ register: range_query_pool
+
+- name: query assertions
+ assert:
+ that:
+ - range_query_pool.current | length == 1
+ - range_query_pool.current.0.fvnsVlanInstP.attributes.name == "anstest"
+ - range_query_pool.current.0.fvnsVlanInstP.children | length > 1
+ - range_query_pool.url.endswith("infra/vlanns-[anstest]-static.json")
+
+- name: query all ranges
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_pool_present
+ state: query
+ pool: '{{ omit }}'
+ register: range_query_all
+
+- name: query assertions
+ assert:
+ that:
+ - range_query_all is not changed
+ - range_query_all.current | length > 1
+ - range_query_all.current.0.fvnsEncapBlk is defined
+ - range_query_all.url.endswith("class/fvnsEncapBlk.json")
+
+- name: delete vlan pool range - deletion works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ state: absent
+ register: delete_range
+
+- name: absent assertions
+ assert:
+ that:
+ - delete_range is changed
+ - delete_range.proposed == {}
+ - delete_range.previous.0.fvnsEncapBlk.attributes.name == "anstest"
+
+- name: delete vlan pool range - check mode works
+ cisco.aci.aci_encap_pool_range: &aci_range_absent
+ <<: *aci_range_present_2
+ state: absent
+ check_mode: true
+ register: delete_check_mode
+
+- name: absent assertions
+ assert:
+ that:
+ - delete_check_mode is changed
+ - delete_check_mode.previous != []
+
+- name: delete vlan pool range - deletion works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_absent
+ register: delete_range_2
+
+- name: absent assertions
+ assert:
+ that:
+ - delete_range_2 is changed
+ - delete_range_2.previous == delete_check_mode.previous
+
+- name: delete vlan pool range again - idempotency works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_absent
+ register: delete_idempotent
+
+- name: absent assertions
+ assert:
+ that:
+ - delete_idempotent is not changed
+ - delete_idempotent.previous == []
+
+- name: cleanup vlan pool
+ 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/vsan.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml
new file mode 100644
index 000000000..7bdc332c5
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml
@@ -0,0 +1,20 @@
+- name: ensure vsan pool exists for tests to kick off
+ 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") }}'
+ pool: anstest
+ pool_type: vsan
+ allocation_mode: static
+ description: Ansible Test
+ state: present
+
+- name: cleanup vsan pool
+ 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
new file mode 100644
index 000000000..e5e301916
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml
@@ -0,0 +1,19 @@
+- name: ensure vxlan pool exists for tests to kick off
+ 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") }}'
+ pool: anstest
+ pool_type: vxlan
+ description: Ansible Test
+ state: present
+
+- name: cleanup vxlan pool
+ 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/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/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/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml
new file mode 100644
index 000000000..ffd3ac599
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml
@@ -0,0 +1,316 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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
+ 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
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: ensure monitoring policy exists
+ cisco.aci.aci_epg_monitoring_policy:
+ 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
+ monitoring_policy: check
+ tenant: ansible_test
+
+ - name: ensure bd exists for tests to kick off
+ cisco.aci.aci_bd: &aci_bd_present
+ <<: *aci_tenant_present
+ bd: anstest
+ register: bd_present
+
+ - name: ensure ap exists for tests to kick off
+ cisco.aci.aci_ap: &aci_ap_present
+ <<: *aci_tenant_present
+ ap: anstest
+ register: ap_present
+
+ - name: create epg - check mode works
+ cisco.aci.aci_epg: &aci_epg_present
+ <<: *aci_ap_present
+ epg: anstest
+ bd: anstest
+ description: Ansible Test
+ monitoring_policy: check
+ custom_qos_policy: check
+ check_mode: true
+ register: epg_present_check_mode
+
+ - name: create epg - creation works
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ register: epg_present
+
+ - name: create epg - idempotency works
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ register: epg_present_idempotent
+
+ - name: update epg - update works
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ description: Ansible Test Update
+ register: epg_present_update
+
+ - name: create epg - missing param
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ ap: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: epg_present_missing_param
+
+ - name: create epg - used for query
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ epg: anstest2
+
+ - name: present assertions
+ assert:
+ that:
+ - epg_present_check_mode is changed
+ - epg_present_check_mode.previous == []
+ - epg_present_check_mode.sent.fvAEPg.attributes != {}
+ - epg_present_check_mode.sent.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == "anstest"
+ - epg_present_check_mode.sent.fvAEPg.children.1.fvRsAEPgMonPol.attributes.tnMonEPGPolName == 'check'
+ - epg_present_check_mode.sent.fvAEPg.children.2.fvRsCustQosPol.attributes.tnQosCustomPolName == 'check'
+ - epg_present is changed
+ - epg_present.sent == epg_present_check_mode.sent
+ - epg_present.current.0.fvAEPg.attributes.annotation == 'orchestrator:ansible'
+ - epg_present_idempotent is not changed
+ - epg_present_idempotent.sent == {}
+ - epg_present_update is changed
+ - epg_present_update.sent.fvAEPg.attributes.descr == 'Ansible Test Update'
+ - epg_present_missing_param is failed
+ - 'epg_present_missing_param.msg == "state is present but all of the following are missing: ap"'
+
+ - name: get specific epg
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ state: query
+ register: epg_query
+
+ - name: get all epgs
+ cisco.aci.aci_epg:
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fakevar | default(omit) }}"
+ register: epg_query_all
+
+ - name: query assertions
+ assert:
+ that:
+ - epg_query is not changed
+ - epg_query.current | length == 1
+ - epg_query.current.0.fvAEPg.attributes.name == "anstest"
+ - epg_query.current.0.fvAEPg.children.1.fvRsCustQosPol.attributes.tnQosCustomPolName == 'check'
+ - epg_query.current.0.fvAEPg.children.2.fvRsAEPgMonPol.attributes.tnMonEPGPolName == 'check'
+ - '"tn-ansible_test/ap-anstest/epg-anstest.json" in epg_query.url'
+ - epg_query_all is not changed
+ - epg_query_all.current | length > 1
+ - '"?rsp-subtree=full&rsp-subtree-class=fvRsAEPgMonPol,fvRsBd" in epg_query_all.filter_string'
+ - '"class/fvAEPg.json" in epg_query_all.url'
+
+ - name: delete epg - check mode works
+ cisco.aci.aci_epg: &aci_epg_absent
+ <<: *aci_epg_present
+ state: absent
+ check_mode: true
+ register: delete_epg_check_mode
+
+ - name: delete epg - delete works
+ cisco.aci.aci_epg:
+ <<: *aci_epg_absent
+ register: delete_epg
+
+ - name: delete epg - idempotency works
+ cisco.aci.aci_epg:
+ <<: *aci_epg_absent
+ register: delete_epg_idempotent
+
+ - name: delete epg - cleanup extra epg
+ cisco.aci.aci_epg:
+ <<: *aci_epg_absent
+ epg: anstest2
+
+ - name: delete epg - missing param fails
+ cisco.aci.aci_epg:
+ <<: *aci_epg_absent
+ tenant: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: delete_epg_missing_param
+
+ - name: query assertions
+ assert:
+ that:
+ - delete_epg_check_mode is changed
+ - delete_epg_check_mode.previous != []
+ - delete_epg is changed
+ - delete_epg.previous == delete_epg_check_mode.previous
+ - delete_epg_idempotent is not changed
+ - delete_epg_idempotent.previous == []
+ - delete_epg_missing_param is failed
+ - 'delete_epg_missing_param.msg == "state is absent but all of the following are missing: tenant"'
+
+ - name: create microsegmented epg with check mode
+ cisco.aci.aci_epg: &cm_useg_epg_present
+ <<: *aci_ap_present
+ epg: anstest_useg_epg
+ bd: anstest
+ useg: yes
+ description: uSeg EPG Ansible Test
+ check_mode: true
+ register: cm_useg_epg_present
+
+ - name: Assertions check for create microsegmented epg with check mode
+ assert:
+ that:
+ - cm_useg_epg_present is changed
+ - cm_useg_epg_present.current == []
+ - cm_useg_epg_present.previous == []
+ - cm_useg_epg_present.sent.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - cm_useg_epg_present.sent.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - cm_useg_epg_present.sent.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+
+ - name: create microsegmented epg with normal mode
+ cisco.aci.aci_epg: &nm_useg_epg_present
+ <<: *cm_useg_epg_present
+ register: nm_useg_epg_present
+
+ - name: Assertions check for create microsegmented epg with normal mode
+ assert:
+ that:
+ - nm_useg_epg_present is changed
+ - nm_useg_epg_present.current | length == 1
+ - nm_useg_epg_present.previous == []
+ - nm_useg_epg_present.current.0.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - nm_useg_epg_present.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - nm_useg_epg_present.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+ - nm_useg_epg_present.sent.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - nm_useg_epg_present.sent.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - nm_useg_epg_present.sent.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+
+ - name: create microsegmented epg with normal mode - idempotency works
+ cisco.aci.aci_epg:
+ <<: *cm_useg_epg_present
+ register: idempotency_nm_useg_epg_present
+
+ - name: Idempotency assertions check for create microsegmented epg with normal mode
+ assert:
+ that:
+ - idempotency_nm_useg_epg_present is not changed
+ - idempotency_nm_useg_epg_present.current | length == 1
+ - idempotency_nm_useg_epg_present.previous | length == 1
+ - idempotency_nm_useg_epg_present.current.0.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - idempotency_nm_useg_epg_present.previous.0.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - idempotency_nm_useg_epg_present.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - idempotency_nm_useg_epg_present.previous.0.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - idempotency_nm_useg_epg_present.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+ - idempotency_nm_useg_epg_present.previous.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+
+ - name: get anstest_useg_epg epg
+ cisco.aci.aci_epg:
+ <<: *nm_useg_epg_present
+ state: query
+ register: useg_epg_present
+
+ - name: Assertions check for query microsegmented epg with normal mode
+ assert:
+ that:
+ - useg_epg_present is not changed
+ - useg_epg_present.current | length == 1
+ - useg_epg_present.current.0.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - useg_epg_present.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - useg_epg_present.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+
+ - name: delete microsegmented epg with check mode
+ cisco.aci.aci_epg: &cm_useg_epg_absent
+ <<: *nm_useg_epg_present
+ state: absent
+ check_mode: true
+ register: cm_useg_epg_absent
+
+ - name: Assertions check for delete microsegmented epg with check mode
+ assert:
+ that:
+ - cm_useg_epg_absent is changed
+ - cm_useg_epg_absent.current | length == 1
+ - cm_useg_epg_absent.previous | length == 1
+ - cm_useg_epg_absent.current.0.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - cm_useg_epg_absent.current.0.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - cm_useg_epg_absent.current.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+ - cm_useg_epg_absent.previous.0.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - cm_useg_epg_absent.previous.0.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - cm_useg_epg_absent.previous.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+
+ - name: delete microsegmented epg with normal mode
+ cisco.aci.aci_epg: &nm_useg_epg_absent
+ <<: *cm_useg_epg_absent
+ state: absent
+ register: nm_useg_epg_absent
+
+ - name: Assertions check for delete microsegmented epg with normal mode
+ assert:
+ that:
+ - nm_useg_epg_absent is changed
+ - nm_useg_epg_absent.current | length == 0
+ - nm_useg_epg_absent.previous | length == 1
+ - nm_useg_epg_absent.previous.0.fvAEPg.attributes.name == 'anstest_useg_epg'
+ - nm_useg_epg_absent.previous.0.fvAEPg.attributes.isAttrBasedEPg == 'yes'
+ - nm_useg_epg_absent.previous.0.fvAEPg.children.0.fvRsBd.attributes.tnFvBDName == 'anstest'
+
+ - name: delete microsegmented epg with normal mode - idempotency works
+ cisco.aci.aci_epg:
+ <<: *nm_useg_epg_absent
+ register: idempotency_nm_useg_epg_absent
+
+ - name: Idempotency assertions check for delete microsegmented epg with normal mode
+ assert:
+ that:
+ - idempotency_nm_useg_epg_absent is not changed
+ - idempotency_nm_useg_epg_absent.current | length == 0
+ - idempotency_nm_useg_epg_absent.previous | length == 0
+
+ - name: cleanup bd
+ cisco.aci.aci_bd:
+ <<: *aci_bd_present
+ state: absent
+ when: bd_present.previous == []
+
+ - name: cleanup ap
+ cisco.aci.aci_ap:
+ <<: *aci_ap_present
+ state: absent
+ when: ap_present.previous == []
+
+ - name: cleanup tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present.previous == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/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_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml
new file mode 100644
index 000000000..ec97334ab
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml
@@ -0,0 +1,265 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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: Ensure contract binding does not exist prior to testing
+ cisco.aci.aci_epg_to_contract:
+ 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
+ ap: anstest
+ epg: anstest
+ contract_type: provider
+ contract: "anstest_http"
+ state: absent
+
+- 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
+ 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
+ tenant: ansible_test
+ state: present
+ register: tenant_present
+
+ - name: ensure contracts exist for tests to kick off
+ cisco.aci.aci_contract:
+ <<: *aci_tenant_present
+ contract: "{{ item }}"
+ with_items: ["anstest_http", "anstest_https", "anstest_db"]
+
+ - name: ensure ap exists
+ cisco.aci.aci_ap: &aci_ap_present
+ <<: *aci_tenant_present
+ ap: anstest
+ register: ap_present
+
+ - name: ensure epg exists
+ cisco.aci.aci_epg: &aci_epg_present
+ <<: *aci_ap_present
+ epg: anstest
+ register: epg_present
+
+ - name: bind contract to epg - check mode works
+ cisco.aci.aci_epg_to_contract: &aci_epg_provide_present
+ <<: *aci_epg_present
+ contract_type: provider
+ contract: anstest_http
+ contract_label: anstest_contract_label
+ subject_label: anstest_subject_label
+ check_mode: true
+ register: provide_present_check_mode
+
+ - name: bind contract to epg - provide works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_provide_present
+ register: provide_present
+
+ - name: bind contract to epg - consume works
+ cisco.aci.aci_epg_to_contract: &aci_epg_consume_present
+ <<: *aci_epg_provide_present
+ contract_type: consumer
+ contract: anstest_db
+ register: consume_present
+
+ - name: bind contract to epg - add additional contract
+ cisco.aci.aci_epg_to_contract: &aci_epg_provide_present2
+ <<: *aci_epg_provide_present
+ contract: anstest_https
+ provider_match: at_most_one
+ contract_label: "{{ fakevar | default(omit) }}"
+ subject_label: "{{ fakevar | default(omit) }}"
+ register: provide_present2
+
+ - name: bind contract to epg - idempotency works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_provide_present
+ register: idempotent_present
+
+ - name: missing param - failure message works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_tenant_present
+ contract_type: provider
+ ignore_errors: true
+ register: missing_param_present
+
+ - name: missing required param - failure message works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_tenant_present
+ ignore_errors: true
+ register: missing_required_present
+
+ - name: incompatible param - failure message works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_consume_present
+ provider_match: all
+ ignore_errors: true
+ register: incompatible_present
+
+ - name: present assertions
+ assert:
+ that:
+ - provide_present_check_mode is changed
+ - provide_present_check_mode.sent.fvRsProv.attributes.tnVzBrCPName == 'anstest_http'
+ - provide_present is changed
+ - provide_present.sent == provide_present_check_mode.sent
+ - provide_present.current.0.fvRsProv.attributes.annotation == 'orchestrator:ansible'
+ - provide_present.previous == []
+ - consume_present is changed
+ - consume_present.previous == []
+ - consume_present.sent.fvRsCons.attributes.tnVzBrCPName == 'anstest_db'
+ - provide_present2 is changed
+ - provide_present2.previous == []
+ - missing_param_present is failed
+ - 'missing_param_present.msg == "state is present but all of the following are missing: ap, contract, epg"'
+ - missing_required_present is failed
+ - 'missing_required_present.msg == "missing required arguments: contract_type"'
+ - incompatible_present is failed
+ - incompatible_present.msg == "the 'provider_match' is only configurable for Provided Contracts"
+
+ - name: get binding
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_provide_present2
+ state: query
+ register: query_provide_contract
+
+ - name: get binding
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_consume_present
+ state: query
+ register: query_consume_contract
+
+ - name: get all bindings
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fakevar | default(omit) }}"
+ contract_type: provider
+ register: query_all
+
+ - name: missing required param - failure message works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_tenant_present
+ state: query
+ ignore_errors: true
+ register: missing_required_query
+
+ - name: query assertions
+ assert:
+ that:
+ - query_provide_contract is not changed
+ - query_provide_contract.current != []
+ - '"uni/tn-ansible_test/ap-anstest/epg-anstest/rsprov-anstest_https.json" in query_provide_contract.url'
+ - query_consume_contract is not changed
+ - query_consume_contract.current != []
+ - '"uni/tn-ansible_test/ap-anstest/epg-anstest/rscons-anstest_db.json" in query_consume_contract.url'
+ - query_all is not changed
+ - '"class/fvRsProv.json" in query_all.url'
+ - missing_required_query is failed
+ - 'missing_required_query.msg == "missing required arguments: contract_type"'
+
+ - name: delete consume binding - check mode works
+ cisco.aci.aci_epg_to_contract: &aci_epg_consume_absent
+ <<: *aci_epg_consume_present
+ state: absent
+ check_mode: true
+ register: consume_absent_check_mode
+
+ - name: delete consume binding - deletion works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_consume_absent
+ register: consume_absent
+
+ - name: delete provide binding - deletion works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_provide_present
+ state: absent
+ register: provide_absent
+
+ - name: delete provide binding - deletion works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_provide_present2
+ state: absent
+ register: provide_absent2
+
+ - name: delete consume binding - idempotency works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_consume_absent
+ register: consume_absent_idempotent
+
+ - name: missing param - failure message works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_consume_absent
+ contract: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: missing_param_absent
+
+ - name: missing required param - failure message works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_consume_absent
+ contract_type: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: missing_required_absent
+
+ - name: absent assertions
+ assert:
+ that:
+ - consume_absent_check_mode is changed
+ - consume_absent_check_mode.previous.0.fvRsCons is defined
+ - consume_absent is changed
+ - consume_absent.previous == consume_absent_check_mode.previous
+ - provide_absent is changed
+ - provide_absent.previous.0.fvRsProv is defined
+ - provide_absent2 is changed
+ - consume_absent_idempotent is not changed
+ - consume_absent_idempotent.previous == []
+ - missing_param_absent is failed
+ - 'missing_param_absent.msg == "state is absent but all of the following are missing: contract"'
+ - missing_required_absent is failed
+ - 'missing_required_absent.msg == "missing required arguments: contract_type"'
+
+ - name: cleanup contracts
+ cisco.aci.aci_contract:
+ <<: *aci_tenant_present
+ state: absent
+ contract: "{{ item }}"
+ with_items: ["anstest_http", "anstest_https", "anstest_db"]
+
+ - name: cleanup epg
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ state: absent
+ when: epg_present is changed
+
+ - name: cleanup ap
+ cisco.aci.aci_ap:
+ <<: *aci_ap_present
+ state: absent
+ when: ap_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_epg_to_contract_interface/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/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_to_contract_interface/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml
new file mode 100644
index 000000000..a7ba64768
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_interface/tasks/main.yml
@@ -0,0 +1,196 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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) }}'
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Ensure ansible_test does not exist prior to testing
+ cisco.aci.aci_tenant: &ansible_test_absent
+ <<: *aci_info
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+
+- name: Ensure ansible_test_2 does not exist prior to testing
+ cisco.aci.aci_tenant: &ansible_test_2_absent
+ <<: *aci_info
+ output_level: debug
+ tenant: ansible_test_2
+ state: absent
+
+- 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 ansible_test exist prior to testing
+ cisco.aci.aci_tenant: &ansible_test_present
+ <<: *ansible_test_absent
+ state: present
+
+ - name: Ensure application profile exist under ansible_test tenant
+ cisco.aci.aci_ap: &anstest1_ap_present
+ <<: *ansible_test_present
+ ap: anstest1_ap
+ state: present
+ register: anstest1_ap_present
+
+ - name: Ensure EPG exist under application profile - anstest1_ap
+ cisco.aci.aci_epg: &anstest1_epg_present
+ <<: *anstest1_ap_present
+ epg: anstest1_epg
+ bd: 'default'
+ description: Ansible Test
+ state: present
+ register: anstest1_epg_present
+
+ - name: Ensure ansible_test_2 exists
+ cisco.aci.aci_tenant: &ansible_test_2_present
+ <<: *ansible_test_2_absent
+ state: present
+
+ - name: Ensure contract exists under ansible_test_2 tenant
+ cisco.aci.aci_contract:
+ <<: *ansible_test_2_present
+ contract: inter_tenant_contract
+ description: Ansible Test
+ scope: global
+ state: present
+ register: inter_tenant_contract
+
+ - name: Ensure inter_tenant_contract exported from ansible_test_2 to ansible_test
+ cisco.aci.aci_contract_export:
+ <<: *aci_info
+ name: inter_tenant_contract_interface
+ destination_tenant: ansible_test
+ contract: inter_tenant_contract
+ tenant: ansible_test_2
+ state: present
+ register: testcif1
+
+ - name: Ensure inter_tenant_contract_interface binding exist in anstest1_epg
+ cisco.aci.aci_epg_to_contract_interface: &contract_interface_binding_present
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest1_ap
+ epg: anstest1_epg
+ contract_interface: inter_tenant_contract_interface
+ state: present
+ register: inter_tenant_contract_interface_present
+
+ - name: Ensure inter_tenant_contract_interface binding with anstest1_epg
+ assert:
+ that:
+ - inter_tenant_contract_interface_present is changed
+ - inter_tenant_contract_interface_present.current | length == 1
+ - inter_tenant_contract_interface_present.current.0.fvRsConsIf.attributes.tnVzCPIfName == 'inter_tenant_contract_interface'
+ - inter_tenant_contract_interface_present.current.0.fvRsConsIf.attributes.prio == 'unspecified'
+ - inter_tenant_contract_interface_present.current.0.fvRsConsIf.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Ensure inter_tenant_contract_interface binding with anstest1_epg - idempotency works
+ cisco.aci.aci_epg_to_contract_interface:
+ <<: *contract_interface_binding_present
+ register: idempotency_check
+
+ - name: Verfication of idempotency_check
+ assert:
+ that:
+ - idempotency_check is not changed
+
+ - name: Query a specific consumed contract interface
+ cisco.aci.aci_epg_to_contract_interface:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest1_ap
+ epg: anstest1_epg
+ contract_interface: inter_tenant_contract_interface
+ state: query
+ register: single_object_query_result
+
+ - name: Verification of single consumed contract interface
+ assert:
+ that:
+ - single_object_query_result is not changed
+ - single_object_query_result.current.0.fvRsConsIf.attributes.tnVzCPIfName == 'inter_tenant_contract_interface'
+ - single_object_query_result.current.0.fvRsConsIf.attributes.tDn == 'uni/tn-ansible_test/cif-inter_tenant_contract_interface'
+ - single_object_query_result.current.0.fvRsConsIf.attributes.prio == 'unspecified'
+ - single_object_query_result.current.0.fvRsConsIf.attributes.state == 'formed'
+
+ - name: Query all consumed contract interfaces
+ cisco.aci.aci_epg_to_contract_interface:
+ <<: *aci_info
+ state: query
+ register: all_object_query_result
+
+ - name: Verification of all consumed contract interface
+ assert:
+ that:
+ - all_object_query_result is not changed
+ - inter_tenant_contract_interface_present.current | length >= 1
+
+ - name: delete consumed contract interface
+ cisco.aci.aci_epg_to_contract_interface:
+ <<: *contract_interface_binding_present
+ state: absent
+
+ - name: Ensure temp_contract exists under ansible_test_2 tenant
+ cisco.aci.aci_contract:
+ <<: *ansible_test_2_present
+ contract: temp_contract
+ description: Ansible Test
+ scope: global
+ state: present
+
+ - name: Negative check with invalid consumed contract interface binding with anstest1_epg
+ cisco.aci.aci_epg_to_contract_interface:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest1_ap
+ epg: anstest1_epg
+ contract_interface: temp_contract # contract was not exported, test expected to fail
+ state: present
+ ignore_errors: true
+
+ - name: check missing parameters while binding consumed contract interface with anstest1_epg
+ cisco.aci.aci_epg_to_contract_interface:
+ <<: *contract_interface_binding_present
+ contract_interface: "{{ fakevar | default(omit) }}"
+ state: present
+ ignore_errors: true
+
+ # cleanup session
+ - name: delete anstest1_epg_present
+ cisco.aci.aci_epg:
+ <<: *anstest1_epg_present
+ state: absent
+
+ - name: delete anstest1_ap_present
+ cisco.aci.aci_ap:
+ <<: *anstest1_ap_present
+ state: absent
+
+ - name: delete ansible_test
+ cisco.aci.aci_tenant:
+ <<: *ansible_test_present
+ state: absent
+
+ - name: delete ansible_test_2
+ cisco.aci.aci_tenant:
+ <<: *ansible_test_2_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/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_to_contract_master/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml
new file mode 100644
index 000000000..08a956f96
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml
@@ -0,0 +1,209 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_password }}'
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent
+
+- 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
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+ - name: ensure contracts exist for tests to kick off
+ cisco.aci.aci_contract:
+ <<: *aci_tenant_present
+ contract: "{{ item }}"
+ with_items: ["anstest_http", "anstest_https", "anstest_db"]
+
+ - name: ensure ap exists for tests to kick off
+ cisco.aci.aci_ap: &aci_ap_present
+ <<: *aci_tenant_present
+ ap: "{{ item }}"
+ register: ap_present
+ loop:
+ - anstest
+ - anstest_2
+
+ - name: create epg
+ cisco.aci.aci_epg: &aci_epg_present
+ <<: *aci_tenant_present
+ ap: anstest
+ epg: anstest
+ register: epg_present
+
+ - name: bind provider contract to epg
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_present
+ contract_type: provider
+ contract: anstest_http
+
+ - name: bind consumer contract to epg
+ cisco.aci.aci_epg_to_contract: &aci_epg_consume_present
+ <<: *aci_epg_present
+ contract_type: consumer
+ contract: anstest_https
+
+ - name: bind consumer contract to epg
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_epg_consume_present
+ contract_type: consumer
+ contract: anstest_db
+
+ - name: create epgs
+ cisco.aci.aci_epg:
+ <<: *aci_tenant_present
+ ap: "{{ item.ap }}"
+ epg: "{{ item.epg }}"
+ register: inherited_epg_present
+ loop:
+ - {ap: 'anstest', epg: 'anstest_2'}
+ - {ap: 'anstest_2', epg: 'anstest_4'}
+ - {ap: 'anstest_2', epg: 'anstest_3'}
+
+ - name: bind provider contract to epg_4
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_tenant_present
+ ap: anstest_2
+ epg: anstest_4
+ contract_type: provider
+ contract: anstest_http
+
+ - name: add contract master
+ cisco.aci.aci_epg_to_contract_master:
+ <<: *aci_tenant_present
+ ap: "{{ item.ap }}"
+ epg: "{{ item.epg }}"
+ contract_master_ap: anstest
+ contract_master_epg: anstest
+ state: present
+ register: add_contract_master
+ loop:
+ - {ap: 'anstest', epg: 'anstest_2'}
+ - {ap: 'anstest_2', epg: 'anstest_3'}
+
+ - name: Verify add_contract_master
+ assert:
+ that:
+ - item is changed
+ - item.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-anstest/epg-anstest"
+ loop: "{{ add_contract_master.results }}"
+
+ - name: add another contract master
+ cisco.aci.aci_epg_to_contract_master:
+ <<: *aci_tenant_present
+ ap: "{{ item.ap }}"
+ epg: "{{ item.epg }}"
+ contract_master_ap: anstest_2
+ contract_master_epg: anstest_4
+ state: present
+ register: add_another_contract_master
+ loop:
+ - {ap: 'anstest', epg: 'anstest_2'}
+ - {ap: 'anstest_2', epg: 'anstest_3'}
+ - name: Verify add_another_contract_master
+ assert:
+ that:
+ - item is changed
+ - item.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-anstest_2/epg-anstest_4"
+ loop: "{{ add_another_contract_master.results }}"
+
+ # Query all contract master ! does not work
+ - name: Query all contract master
+ cisco.aci.aci_epg_to_contract_master:
+ <<: *aci_tenant_present
+ ap: anstest
+ epg: anstest_2
+ state: query
+ register: query_all
+
+ # Query specific contract master
+ - name: Query specific contract master
+ cisco.aci.aci_epg_to_contract_master:
+ <<: *aci_tenant_present
+ ap: anstest
+ epg: anstest_2
+ contract_master_ap: anstest_2
+ contract_master_epg: anstest_4
+ state: query
+ register: query_specific_contract_master
+
+ - name: Verify query_specific_contract_master
+ assert:
+ that:
+ - query_specific_contract_master is not changed
+ - query_specific_contract_master.current.0.fvRsSecInherited.attributes.dn == "uni/tn-ansible_test/ap-anstest/epg-anstest_2/rssecInherited-[uni/tn-ansible_test/ap-anstest_2/epg-anstest_4]"
+ - query_specific_contract_master.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-anstest_2/epg-anstest_4"
+
+ # Query specific contract master
+ - name: Query another specific contract master
+ cisco.aci.aci_epg_to_contract_master:
+ <<: *aci_tenant_present
+ ap: anstest
+ epg: anstest_2
+ contract_master_ap: anstest
+ contract_master_epg: anstest
+ state: query
+ register: query_another_specific_contract_master
+
+ - name: Verify query_another_specific_contract_master
+ assert:
+ that:
+ - query_another_specific_contract_master is not changed
+ - query_another_specific_contract_master.current.0.fvRsSecInherited.attributes.dn == "uni/tn-ansible_test/ap-anstest/epg-anstest_2/rssecInherited-[uni/tn-ansible_test/ap-anstest/epg-anstest]"
+ - query_another_specific_contract_master.current.0.fvRsSecInherited.attributes.annotation == 'orchestrator:ansible'
+ - query_another_specific_contract_master.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-anstest/epg-anstest"
+
+ - name: Remove specific contract master
+ cisco.aci.aci_epg_to_contract_master:
+ <<: *aci_tenant_present
+ ap: anstest
+ epg: anstest_2
+ contract_master_ap: anstest
+ contract_master_epg: anstest
+ state: absent
+ register: remove_contract_master
+
+ - name: Verify remove_contract_master
+ assert:
+ that:
+ - remove_contract_master is changed
+ - remove_contract_master.current == []
+
+ # Clean up environment
+ - name: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ register: tenant_absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/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_to_domain/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml
new file mode 100644
index 000000000..ea482f563
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml
@@ -0,0 +1,735 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("debug") }}'
+
+- name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: ensure tenant exists for tests to kick off
+ cisco.aci.aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+ register: tenant_present
+ - name: ensure ap exists for tests to kick off
+ cisco.aci.aci_ap: &aci_ap_present
+ <<: *aci_tenant_present
+ ap: anstest
+ register: ap_present
+
+ - name: delete epg to make sure setup is clean
+ cisco.aci.aci_epg:
+ <<: *aci_ap_present
+ epg: anstest
+ state: absent
+
+ - 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: ensure phys domain exists for tests to kick off
+ cisco.aci.aci_rest: &aci_rest_phys_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") }}'
+ method: post
+ path: api/mo/uni/phys-anstest.json
+ content: {"physDomP": {"attributes": {}}}
+ register: phys_domain_post
+
+ - name: ensure vmm domain exists for tests to kick off
+ cisco.aci.aci_rest: &aci_rest_vmm_domain
+ <<: *aci_rest_phys_domain
+ path: api/mo/uni/vmmp-VMware/dom-anstest.json
+ content: {"vmmDomP": {"attributes": {}}}
+ register: vmm_domain_post
+
+ - name: ensure l2dom domain exists for tests to kick off
+ cisco.aci.aci_rest: &aci_rest_l2dom_domain
+ <<: *aci_rest_phys_domain
+ path: api/mo/uni/l2dom-anstest.json
+ content: {"l2extDomP": {"attributes": {}}}
+ register: l2dom_domain_post
+
+ - name: bind phys domain to epg - check mode works
+ cisco.aci.aci_epg_to_domain: &aci_epg_to_domain_present
+ <<: *aci_epg_present
+ domain: anstest
+ domain_type: phys
+ check_mode: true
+ register: phys_check_mode_present
+
+ - name: bind phys domain to epg - creation works
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ register: phys_present
+
+ - name: bind phys domain to epg - idempotency works
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ register: phys_idempotent
+
+ - name: bind phys domain to epg - update works
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ deploy_immediacy: immediate
+ register: phys_update
+
+ - name: bind l2dom domain to epg
+ cisco.aci.aci_epg_to_domain: &aci_epg_to_domain_l2dom_present
+ <<: *aci_epg_present
+ domain: anstest
+ domain_type: l2dom
+ register: l2_present
+
+ - name: bind vmm domain to epg - creation works
+ cisco.aci.aci_epg_to_domain: &aci_epg_to_domain_vmm_present
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ resolution_immediacy: pre-provision
+ promiscuous: accept
+ register: vmm_present_promiscuous_accept
+
+ - name: bind vmm domain to epg - creation works
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ resolution_immediacy: pre-provision
+ promiscuous: reject
+ register: vmm_present_promiscuous_reject
+
+ - name: bind vmm domain to epg - missing params
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_vmm_present
+ vm_provider: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: present_missing_params
+
+ - name: bind vmm domain to epg - valid vlan
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ encap: 1
+ register: valid_vlan
+
+ - name: bind vmm domain to epg - valid vlan (primary_encap)
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ primary_encap: 25
+ register: valid_vlan_primary_encap
+
+ - name: bind vmm domain to epg - invalid vlan
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ encap: 4097
+ ignore_errors: true
+ register: invalid_vlan
+
+ - name: bind vmm domain to epg - invalid vlan (primary_encap)
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ primary_encap: 4097
+ ignore_errors: true
+ register: invalid_vlan_primary_encap
+
+ - name: bind vmm domain to epg - incompatible params
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ vm_provider: vmware
+ ignore_errors: true
+ register: incompatible_params
+
+ - name: Create enhanced lag policy
+ cisco.aci.aci_rest: &enhanced_lag_policy_present
+ <<: *aci_info
+ path: api/node/mo/uni/vmmp-VMware/dom-anstest/vswitchpolcont.json
+ method: post
+ content: |
+ {
+ "vmmVSwitchPolicyCont": {
+ "attributes": {
+ "dn": "uni/vmmp-VMware/dom-anstest/vswitchpolcont",
+ "status": "created,modified"
+ },
+ "children": [{
+ "lacpEnhancedLagPol": {
+ "attributes": {
+ "lbmode": "src-dst-ip",
+ "mode": "active",
+ "name": "enhanced",
+ "numLinks": "2"
+ }
+ }
+ }]
+ }
+ }
+ register: add_enhanced_lag_policy
+
+ - name: bind vmm domain to epg - enhanced_lag_policy
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ enhanced_lag_policy: enhanced
+ register: enhanced_lag_policy
+
+ - name: Initialize and test active/stanby vmm uplinks
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+ block:
+ - name: bind vmm domain to epg - vmm_uplink
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_active: [ 1, 2 ]
+ vmm_uplink_standby: [ 3, 4 ]
+ register: vmm_uplink
+
+ - name: bind vmm domain to epg - vmm_uplink change standby
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_standby: [ 5, 6 ]
+ register: vmm_uplink_change_standby
+
+ - name: bind vmm domain to epg - vmm_uplink change active
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_active: [ 3, 4 ]
+ register: vmm_uplink_change_active
+
+ - name: vmm_uplink assertions
+ assert:
+ that:
+ - vmm_uplink is changed
+ - vmm_uplink.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "1,2"
+ - vmm_uplink.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.standby == "3,4"
+ - vmm_uplink_change_standby is changed
+ - vmm_uplink_change_standby.previous.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "1,2"
+ - vmm_uplink_change_standby.previous.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.standby == "3,4"
+ - vmm_uplink_change_standby.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "1,2"
+ - vmm_uplink_change_standby.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.standby == "5,6"
+ - vmm_uplink_change_active is changed
+ - vmm_uplink_change_active.previous.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "1,2"
+ - vmm_uplink_change_active.previous.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.standby == "5,6"
+ - vmm_uplink_change_active.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "3,4"
+ - vmm_uplink_change_active.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.standby == "5,6"
+
+ - name: bind vmm domain to epg - vmm_uplink change standby to same as active
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_standby: [ 3, 4 ]
+ register: vmm_uplink_change_active_same_as_standby
+ ignore_errors: true
+
+ - name: bind vmm domain to epg - vmm_uplink change 0 value
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_active: [ 0 ]
+ register: vmm_uplink_0_value
+
+ - name: bind vmm domain to epg - vmm_uplink change 32 value
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_active: [ 32 ]
+ register: vmm_uplink_32_value
+
+ - name: bind vmm domain to epg - vmm_uplink change empty value standby
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_standby: []
+ register: vmm_uplink_empty_value_standby
+
+ - name: vmm_uplink assertions
+ assert:
+ that:
+ - vmm_uplink_0_value is changed
+ - vmm_uplink_0_value.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "0"
+ - vmm_uplink_32_value is changed
+ - vmm_uplink_32_value.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.active == "32"
+ - vmm_uplink_empty_value_standby is changed
+ - vmm_uplink_empty_value_standby.current.0.fvRsDomAtt.children.0.fvUplinkOrderCont.attributes.standby == ""
+
+ - name: bind vmm domain to epg - vmm_uplink change empty value active
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_active: []
+ ignore_errors: true
+ register: vmm_uplink_empty_value_active
+
+ - name: bind vmm domain to epg - vmm_uplink change string value
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_active: [ testing ]
+ ignore_errors: true
+ register: vmm_uplink_string_value
+
+ - name: bind vmm domain to epg - vmm_uplink change 33 value
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ vmm_uplink_active: [ 33 ]
+ ignore_errors: true
+ register: vmm_uplink_33_value
+
+ - name: vmm_uplink error assertions
+ assert:
+ that:
+ - 'vmm_uplink_change_active_same_as_standby.msg == "APIC Error 120: Invalid Configuration. Uplink Id entered more than once or delimiter was misused."'
+ - 'vmm_uplink_empty_value_active.msg == "APIC Error 801: property active of uni/tn-ansible_test/ap-anstest/epg-anstest/rsdomAtt-[uni/vmmp-VMware/dom-anstest]/uplinkorder failed validation for value ''''"'
+ - 'vmm_uplink_string_value.msg == "APIC Error 801: property active of uni/tn-ansible_test/ap-anstest/epg-anstest/rsdomAtt-[uni/vmmp-VMware/dom-anstest]/uplinkorder failed validation for value ''testing''"'
+
+ - name: vmm_uplink error assertions for non-cloud
+ assert:
+ that:
+ - 'vmm_uplink_33_value.msg == "APIC Error 120: Invalid Configuration. Uplink Id can not be higher than 32."'
+
+ - name: change custom epg name
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain_type: vmm
+ vm_provider: vmware
+ custom_epg_name: anstest_epg
+ register: custom_epg_name
+
+ - name: Verify custom epg name
+ assert:
+ that:
+ - custom_epg_name.current.0.fvRsDomAtt.attributes.customEpgName == "anstest_epg"
+
+ - name: domain with delimiter
+ cisco.aci.aci_epg_to_domain: &aci_delimiter
+ <<: *aci_epg_to_domain_present
+ domain: "ansdelim_{{ index }}"
+ domain_type: vmm
+ vm_provider: vmware
+ delimiter: "{{ item }}"
+ register: delimeter
+ loop:
+ - "|"
+ - "~"
+ - "!"
+ - "@"
+ - "^"
+ - "+"
+ - "="
+ loop_control:
+ index_var: index
+
+ - name: domain with delimiter not allowed input
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_delimiter
+ domain: ansdelim_not_allowed
+ delimiter: not_allowed
+ register: delimiter_not_allowed
+ ignore_errors: true
+
+ - name: delete domains with delimiter
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_present
+ domain: "ansdelim_{{ item }}"
+ domain_type: vmm
+ vm_provider: vmware
+ state: absent
+ register: delimeter_absent
+ loop: "{{ range(0, 7, 1)|list }}"
+
+ - name: domains with delimiter assertions
+ assert:
+ that:
+ - delimeter.results.0 is changed
+ - delimeter.results.0.current.0.fvRsDomAtt.attributes.delimiter == "|"
+ - delimeter.results.1 is changed
+ - delimeter.results.1.current.0.fvRsDomAtt.attributes.delimiter == "~"
+ - delimeter.results.2 is changed
+ - delimeter.results.2.current.0.fvRsDomAtt.attributes.delimiter == "!"
+ - delimeter.results.3 is changed
+ - delimeter.results.3.current.0.fvRsDomAtt.attributes.delimiter == "@"
+ - delimeter.results.4 is changed
+ - delimeter.results.4.current.0.fvRsDomAtt.attributes.delimiter == "^"
+ - delimeter.results.5 is changed
+ - delimeter.results.5.current.0.fvRsDomAtt.attributes.delimiter == "+"
+ - delimeter.results.6 is changed
+ - delimeter.results.6.current.0.fvRsDomAtt.attributes.delimiter == "="
+ - delimiter_not_allowed is not changed
+ - 'delimiter_not_allowed.msg == "value of delimiter must be one of: |, ~, !, @, ^, +, =, got: not_allowed"'
+ - delimeter_absent.results.0 is changed
+ - delimeter_absent.results.0.current == []
+ - delimeter_absent.results.1 is changed
+ - delimeter_absent.results.1.current == []
+ - delimeter_absent.results.2 is changed
+ - delimeter_absent.results.2.current == []
+ - delimeter_absent.results.3 is changed
+ - delimeter_absent.results.3.current == []
+ - delimeter_absent.results.4 is changed
+ - delimeter_absent.results.4.current == []
+ - delimeter_absent.results.5 is changed
+ - delimeter_absent.results.5.current == []
+ - delimeter_absent.results.6 is changed
+ - delimeter_absent.results.6.current == []
+
+ - name: domain with untagged vlan true
+ cisco.aci.aci_epg_to_domain: &aci_untagged
+ <<: *aci_epg_to_domain_present
+ domain: ansuntagged
+ domain_type: vmm
+ vm_provider: vmware
+ untagged_vlan: true
+ register: untagged_vlan_true
+
+ - name: domain with untagged vlan false
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_untagged
+ untagged_vlan: false
+ register: untagged_vlan_false
+
+ - name: delete domain with untagged vlan
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_untagged
+ state: absent
+ register: untagged_vlan_absent
+
+ - name: domains with untagged vlan assertions
+ assert:
+ that:
+ - untagged_vlan_true is changed
+ - untagged_vlan_true.current.0.fvRsDomAtt.attributes.untagged == "yes"
+ - untagged_vlan_false is changed
+ - untagged_vlan_false.current.0.fvRsDomAtt.attributes.untagged == "no"
+ - untagged_vlan_absent is changed
+ - untagged_vlan_absent.current == []
+
+ - name: Test domain with port binding
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+ block:
+ - name: domain with port binding dynamic
+ cisco.aci.aci_epg_to_domain: &aci_port_binding
+ <<: *aci_epg_to_domain_present
+ domain: ansportbind
+ domain_type: vmm
+ vm_provider: vmware
+ port_binding: dynamic
+ register: port_binding_dynamic
+
+ - name: change domain with port binding to static
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_port_binding
+ port_binding: static
+ register: port_binding_static
+
+ - name: change domain with port binding to ephemeral
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_port_binding
+ port_binding: ephemeral
+ register: port_binding_ephemeral
+
+ - name: domain with port binding not allowed input
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_port_binding
+ domain: ansdelim_not_allowed
+ port_binding: not_allowed
+ register: port_binding_not_allowed
+ ignore_errors: true
+
+ - name: delete domain with port binding
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_port_binding
+ state: absent
+ register: port_binding_absent
+
+ - name: domains with port binding assertions
+ assert:
+ that:
+ - port_binding_dynamic is changed
+ - port_binding_dynamic.current.0.fvRsDomAtt.attributes.bindingType == "dynamicBinding"
+ - port_binding_static is changed
+ - port_binding_static.current.0.fvRsDomAtt.attributes.bindingType == "staticBinding"
+ - port_binding_ephemeral is changed
+ - port_binding_ephemeral.current.0.fvRsDomAtt.attributes.bindingType == "ephemeral"
+ - port_binding_not_allowed is not changed
+ - 'port_binding_not_allowed.msg == "value of port_binding must be one of: dynamic, ephemeral, static, got: not_allowed"'
+ - port_binding_absent is changed
+ - port_binding_absent.current == []
+
+ - name: domain with port allocation elastic
+ cisco.aci.aci_epg_to_domain: &aci_port_allocation
+ <<: *aci_epg_to_domain_present
+ domain: ansportalloc
+ domain_type: vmm
+ vm_provider: vmware
+ port_allocation: elastic
+ register: port_allocation_elastic
+
+ - name: change domain with port allocation to fixed
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_port_allocation
+ port_allocation: fixed
+ register: port_allocation_fixed
+
+ - name: domain with port allocation not allowed input
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_port_allocation
+ domain: ansdelim_not_allowed
+ port_allocation: not_allowed
+ register: port_allocation_not_allowed
+ ignore_errors: true
+
+ - name: delete domain with port allocation
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_port_allocation
+ state: absent
+ register: port_allocation_absent
+
+ - name: domains with port allocation assertions
+ assert:
+ that:
+ - port_allocation_elastic is changed
+ - port_allocation_elastic.current.0.fvRsDomAtt.attributes.portAllocation == "elastic"
+ - port_allocation_fixed is changed
+ - port_allocation_fixed.current.0.fvRsDomAtt.attributes.portAllocation == "fixed"
+ - port_allocation_not_allowed is not changed
+ - 'port_allocation_not_allowed.msg == "value of port_allocation must be one of: elastic, fixed, got: not_allowed"'
+ - port_allocation_absent is changed
+ - port_allocation_absent.current == []
+
+ - name: domain with number of ports of 2
+ cisco.aci.aci_epg_to_domain: &aci_number_port
+ <<: *aci_epg_to_domain_present
+ domain: ansportnum
+ domain_type: vmm
+ vm_provider: vmware
+ number_of_ports: 2
+ register: number_of_ports_2
+
+ - name: change domain with number of ports to 3
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_number_port
+ number_of_ports: 3
+ register: number_of_ports_3
+
+ - name: delete domain with number of ports
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_number_port
+ state: absent
+ register: number_of_ports_absent
+
+ - name: domains with number of ports assertions
+ assert:
+ that:
+ - number_of_ports_2 is changed
+ - number_of_ports_2.current.0.fvRsDomAtt.attributes.numPorts == "2"
+ - number_of_ports_3 is changed
+ - number_of_ports_3.current.0.fvRsDomAtt.attributes.numPorts == "3"
+ - number_of_ports_absent is changed
+ - number_of_ports_absent.current == []
+
+ - name: domain with forged transmits and mac changes
+ cisco.aci.aci_epg_to_domain: &aci_forged_transmits_and_mac_changes
+ <<: *aci_epg_to_domain_present
+ domain: ansforgedmac
+ domain_type: vmm
+ vm_provider: vmware
+ forged_transmits: accept
+ mac_changes: accept
+ register: forged_transmits_and_mac_changes_accept
+
+ - name: change domain with forged transmits and mac changes to reject
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_forged_transmits_and_mac_changes
+ forged_transmits: reject
+ mac_changes: reject
+ register: forged_transmits_and_mac_changes_reject
+
+ - name: delete domain with forged transmits and mac changes
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_forged_transmits_and_mac_changes
+ state: absent
+ register: forged_transmits_and_mac_changes_absent
+
+ - name: domains with forged transmits and mac changes assertions
+ assert:
+ that:
+ - forged_transmits_and_mac_changes_accept is changed
+ - forged_transmits_and_mac_changes_accept.current.0.fvRsDomAtt.children.0.vmmSecP.attributes.forgedTransmits == "accept"
+ - forged_transmits_and_mac_changes_accept.current.0.fvRsDomAtt.children.0.vmmSecP.attributes.macChanges == "accept"
+ - forged_transmits_and_mac_changes_reject is changed
+ - forged_transmits_and_mac_changes_reject.current.0.fvRsDomAtt.children.0.vmmSecP.attributes.forgedTransmits == "reject"
+ - forged_transmits_and_mac_changes_reject.current.0.fvRsDomAtt.children.0.vmmSecP.attributes.macChanges == "reject"
+ - forged_transmits_and_mac_changes_absent is changed
+ - forged_transmits_and_mac_changes_absent.current == []
+
+ - name: present assertions
+ assert:
+ that:
+ - phys_check_mode_present is changed
+ - phys_present is changed
+ - phys_present.previous == []
+ - phys_present.sent.fvRsDomAtt.attributes.switchingMode == 'native'
+ - phys_present.current.0.fvRsDomAtt.attributes.annotation == 'orchestrator:ansible'
+ - '"[uni/phys-anstest].json" in phys_present.url'
+ - phys_idempotent is not changed
+ - phys_idempotent.sent == {}
+ - phys_update is changed
+ - phys_update.sent.fvRsDomAtt.attributes.instrImedcy == 'immediate'
+ - vmm_present_promiscuous_accept is changed
+ - vmm_present_promiscuous_reject is changed
+ - vmm_present_promiscuous_accept.current.0.fvRsDomAtt.children.0.vmmSecP.attributes.allowPromiscuous == 'accept'
+ - vmm_present_promiscuous_reject.current.0.fvRsDomAtt.children.0.vmmSecP.attributes.allowPromiscuous == 'reject'
+ - vmm_present_promiscuous_accept.sent.fvRsDomAtt.attributes.resImedcy == 'pre-provision'
+ - vmm_present_promiscuous_accept.sent.fvRsDomAtt.attributes.switchingMode == 'native'
+ - '"[uni/vmmp-VMware/dom-anstest].json" in vmm_present_promiscuous_accept.url'
+ - present_missing_params is failed
+ - 'present_missing_params.msg == "domain_type is vmm but all of the following are missing: vm_provider"'
+ - invalid_vlan is failed
+ - invalid_vlan.msg == "Valid VLAN assignments are from 1 to 4096"
+ - incompatible_params is failed
+ - incompatible_params.msg == "Domain type 'phys' cannot have a 'vm_provider'"
+ - invalid_vlan_primary_encap.msg == "Valid VLAN assignments are from 1 to 4096"
+ - '"[uni/l2dom-anstest].json" in l2_present.url'
+ - valid_vlan_primary_encap.current.0.fvRsDomAtt.attributes.dn == "uni/tn-ansible_test/ap-anstest/epg-anstest/rsdomAtt-[uni/phys-anstest]"
+ - enhanced_lag_policy.current.0.fvRsDomAtt.children | length == 2
+ - enhanced_lag_policy.current.0.fvRsDomAtt.children.0.fvAEPgLagPolAtt.children.0.fvRsVmmVSwitchEnhancedLagPol.attributes.tDn == "uni/vmmp-VMware/dom-anstest/vswitchpolcont/enlacplagp-enhanced"
+
+ - name: get domain epg binding
+ cisco.aci.aci_epg_to_domain: &aci_epg_domain_query
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fake_var | default(omit) }}"
+ register: binding_query
+
+ - name: query assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query.current | length > 1
+ - '"class/fvRsDomAtt.json" in binding_query.url'
+
+ - name: delete domain epg binding - check mode
+ cisco.aci.aci_epg_to_domain: &aci_epg_to_domain_absent
+ <<: *aci_epg_to_domain_present
+ state: absent
+ check_mode: true
+ register: epg_domain_check_mode_absent
+
+ - name: delete phys domain epg binding - delete works
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_absent
+ register: epg_domain_absent
+
+ - name: delete vmm domain epg binding - delete works
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_vmm_present
+ state: absent
+ register: epg_vmm_domain_absent
+
+ - name: delete domain epg binding - idempotency works
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_epg_to_domain_absent
+ register: idempotency_absent
+
+ - name: delete domain epg binding - missing param
+ cisco.aci.aci_epg_to_domain:
+ <<: *aci_tenant_present
+ state: absent
+ ignore_errors: true
+ register: absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - epg_domain_check_mode_absent is changed
+ - epg_domain_check_mode_absent.previous != []
+ - epg_domain_absent is changed
+ - epg_domain_absent.previous == epg_domain_check_mode_absent.previous
+ - epg_vmm_domain_absent is changed
+ - idempotency_absent is not changed
+ - idempotency_absent.previous == []
+ - absent_missing_param is failed
+ - 'absent_missing_param.msg == "state is absent but all of the following are missing: ap, domain, domain_type, epg"'
+
+ - name: remove vmm domain - cleanup
+ cisco.aci.aci_rest:
+ <<: *aci_rest_vmm_domain
+ method: delete
+ when: vmm_domain_post is changed
+
+ - name: remove phys domain - cleanup
+ cisco.aci.aci_rest:
+ <<: *aci_rest_phys_domain
+ method: delete
+ when: phys_domain_post is changed
+
+ - name: remove l2 domain - cleanup
+ cisco.aci.aci_rest:
+ <<: *aci_rest_l2dom_domain
+ method: delete
+ when: l2dom_domain_post is changed
+
+ - name: remove epg - cleanup
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ state: absent
+ when: epg_present is changed
+
+ - name: remove ap - cleanup
+ cisco.aci.aci_ap:
+ <<: *aci_ap_present
+ state: absent
+ when: ap_present is changed
+
+ - name: remove tenant - cleanup
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present is changed \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml
new file mode 100644
index 000000000..34a482fa9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg/tasks/main.yml
@@ -0,0 +1,306 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Ensure tenant - ansible_test does not exists before testing
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+
+- name: Execute tasks only for ACI v5+ and non-cloud sites
+ when:
+ - version.current.0.topSystem.attributes.version is version('5', '>=')
+ - query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ # Setup part
+ - name: Ensure ansible_test - tenant exists
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Ensure ap - application profile exists
+ cisco.aci.aci_ap: &anstest_ap_present
+ <<: *tenant_present
+ ap: anstest_ap
+ state: present
+
+ - name: Ensure anstest_ap_1 - application profile exists
+ cisco.aci.aci_ap: &anstest_ap_1_present
+ <<: *tenant_present
+ ap: anstest_ap_1
+ state: present
+
+ # Test Part
+ - name: Ensure web_esg_0 - endpoint security group exists with check mode
+ cisco.aci.aci_esg: &cm_web_esg_0_present
+ <<: *anstest_ap_present
+ esg: web_esg_0
+ vrf: default
+ state: present
+ check_mode: true
+ register: cm_web_esg_0_present
+
+ - name: Assertions check for add web_esg_0 with check mode
+ assert:
+ that:
+ - cm_web_esg_0_present is changed
+ - cm_web_esg_0_present.current | length == 0
+ - cm_web_esg_0_present.previous | length == 0
+
+ - name: Ensure web_esg_0 - endpoint security group exists with normal mode
+ cisco.aci.aci_esg: &nm_web_esg_0_present
+ <<: *cm_web_esg_0_present
+ register: nm_web_esg_0_present
+
+ - name: Assertions check for add web_esg_0 with normal mode
+ assert:
+ that:
+ - nm_web_esg_0_present is changed
+ - nm_web_esg_0_present.current | length == 1
+ - nm_web_esg_0_present.previous | length == 0
+ - nm_web_esg_0_present.current.0.fvESg.attributes.name == 'web_esg_0'
+ - nm_web_esg_0_present.current.0.fvESg.attributes.prio == 'unspecified'
+ - nm_web_esg_0_present.current.0.fvESg.attributes.prefGrMemb == 'exclude'
+ - nm_web_esg_0_present.current.0.fvESg.attributes.pcEnfPref == 'unenforced'
+ - nm_web_esg_0_present.current.0.fvESg.attributes.annotation == 'orchestrator:ansible'
+ - nm_web_esg_0_present.current.0.fvESg.children[0].fvRsScope.attributes.tnFvCtxName == 'default'
+
+ - name: Assertions check for add web_esg_0 with normal mode (v5.2+)
+ assert:
+ that:
+ - nm_web_esg_0_present.current.0.fvESg.attributes.shutdown == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Ensure web_esg_0 - endpoint security group exists with normal mode - idempotency works
+ cisco.aci.aci_esg:
+ <<: *nm_web_esg_0_present
+ register: idempotency_web_esg_0_present
+
+ - name: Idempotency assertions check for add web_esg_0 with normal mode
+ assert:
+ that:
+ - idempotency_web_esg_0_present is not changed
+ - idempotency_web_esg_0_present.current | length == 1
+ - idempotency_web_esg_0_present.previous | length == 1
+ - idempotency_web_esg_0_present.current.0.fvESg.attributes.name == 'web_esg_0'
+
+ - name: Ensure web_esg_0 - endpoint security group exists under ap(anstest_ap_1_present)
+ cisco.aci.aci_esg:
+ <<: *anstest_ap_1_present
+ esg: web_esg_0
+ vrf: default
+ state: present
+ register: ap_1_web_esg_0_present
+
+ - name: Assertions check for add web_esg_0 under ap(anstest_ap_1_present)
+ assert:
+ that:
+ - ap_1_web_esg_0_present is changed
+ - ap_1_web_esg_0_present.current | length == 1
+ - ap_1_web_esg_0_present.previous | length == 0
+ - ap_1_web_esg_0_present.current.0.fvESg.attributes.name == 'web_esg_0'
+ - ap_1_web_esg_0_present.current.0.fvESg.attributes.dn == "uni/tn-ansible_test/ap-anstest_ap_1/esg-web_esg_0"
+
+ - name: Ensure web_esg_1 - endpoint security group exists with admin_state(false -> no) - 'Admin Up' on the UI side
+ cisco.aci.aci_esg:
+ <<: *anstest_ap_present
+ esg: web_esg_1
+ vrf: default
+ admin_state: false
+ state: present
+ register: web_esg_1_present
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Assertions check for add web_esg_1
+ assert:
+ that:
+ - web_esg_1_present is changed
+ - web_esg_1_present.current | length == 1
+ - web_esg_1_present.previous | length == 0
+ - web_esg_1_present.current.0.fvESg.attributes.name == 'web_esg_1'
+ - web_esg_1_present.current.0.fvESg.children[0].fvRsScope.attributes.tnFvCtxName == 'default'
+ - web_esg_1_present.current.0.fvESg.attributes.shutdown == 'no'
+ - web_esg_1_present.sent.fvESg.attributes.shutdown == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Ensure web_esg_2 - endpoint security group exists with admin_state(true -> yes) - 'Admin Shut' on the UI side
+ cisco.aci.aci_esg:
+ <<: *anstest_ap_present
+ esg: web_esg_2
+ admin_state: true
+ vrf: default
+ state: present
+ register: web_esg_2_present
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Assertions check for add web_esg_2
+ assert:
+ that:
+ - web_esg_2_present is changed
+ - web_esg_2_present.current | length == 1
+ - web_esg_2_present.previous | length == 0
+ - web_esg_2_present.current.0.fvESg.attributes.name == 'web_esg_2'
+ - web_esg_2_present.current.0.fvESg.attributes.shutdown == 'yes'
+ - web_esg_2_present.current.0.fvESg.children[0].fvRsScope.attributes.tnFvCtxName == 'default'
+ - web_esg_2_present.sent.fvESg.attributes.shutdown == 'yes'
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Query an ESG
+ cisco.aci.aci_esg:
+ <<: *anstest_ap_present
+ esg: web_esg_0
+ state: query
+ register: query_web_esg_0
+
+ - name: Assertions check for query an ESG(web_esg_0) under ap(anstest_ap)
+ assert:
+ that:
+ - query_web_esg_0 is not changed
+ - query_web_esg_0.current | length == 1
+ - query_web_esg_0.current.0.fvESg.attributes.name == 'web_esg_0'
+ - query_web_esg_0.current.0.fvESg.attributes.dn == "uni/tn-ansible_test/ap-anstest_ap/esg-web_esg_0"
+
+ - name: Assertions check for query an ESG(web_esg_0) under ap(anstest_ap) (v5.2+)
+ assert:
+ that:
+ - query_web_esg_0.current.0.fvESg.attributes.shutdown == 'no'
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Query all ESGs
+ cisco.aci.aci_esg:
+ <<: *aci_info
+ state: query
+ register: query_all_esg
+
+ - name: Assertions check for query all ESGs
+ assert:
+ that:
+ - query_all_esg is not changed
+ - query_all_esg.current | length >= 2 # Count of ESGs added in the above tasks
+ when: version.current.0.topSystem.attributes.version is version('5.2', '<')
+
+ - name: Assertions check for query all ESGs
+ assert:
+ that:
+ - query_all_esg is not changed
+ - query_all_esg.current | length >= 4 # Count of ESGs added in the above tasks
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Query all ESGs with a Specific Name
+ cisco.aci.aci_esg:
+ <<: *aci_info
+ esg: web_esg_0
+ state: query
+ register: query_all_esg_with_name
+
+ - name: Assertions check for query all ESGs with a Specific Name
+ assert:
+ that:
+ - query_all_esg_with_name is not changed
+ - query_all_esg_with_name.current | length >= 2
+
+ - name: Query all ESGs of an App Profile
+ cisco.aci.aci_esg:
+ <<: *aci_info
+ ap: anstest_ap
+ state: query
+ register: query_all_ap_esg
+
+ - name: Assertions check for query all ESGs of an App Profile (<v5.2)
+ assert:
+ that:
+ - query_all_ap_esg is not changed
+ - query_all_ap_esg.current.0.fvAp.attributes.name == 'anstest_ap'
+ - query_all_ap_esg.current.0.fvAp.children | length == 1
+ when: version.current.0.topSystem.attributes.version is version('5.2', '<')
+
+ - name: Assertions check for query all ESGs of an App Profile (>=v5.2)
+ assert:
+ that:
+ - query_all_ap_esg is not changed
+ - query_all_ap_esg.current.0.fvAp.attributes.name == 'anstest_ap'
+ - query_all_ap_esg.current.0.fvAp.children | length == 3
+ when: version.current.0.topSystem.attributes.version is version('5.2', '>=')
+
+ - name: Remove an ESG with check mode
+ cisco.aci.aci_esg: &cm_web_esg_0_absent
+ <<: *anstest_ap_present
+ esg: web_esg_0
+ state: absent
+ register: cm_web_esg_0_absent
+ check_mode: true
+
+ - name: Assertions check for remove an ESG with check mode
+ assert:
+ that:
+ - cm_web_esg_0_absent is changed
+ - cm_web_esg_0_absent.current | length == 1
+ - cm_web_esg_0_absent.previous | length == 1
+ - cm_web_esg_0_absent.current.0.fvESg.attributes.name == 'web_esg_0'
+ - cm_web_esg_0_absent.previous.0.fvESg.attributes.name == 'web_esg_0'
+
+ - name: Remove an ESG with normal mode
+ cisco.aci.aci_esg: &nm_web_esg_0_absent
+ <<: *cm_web_esg_0_absent
+ register: nm_web_esg_0_absent
+
+ - name: Assertions check for remove an ESG with normal mode
+ assert:
+ that:
+ - nm_web_esg_0_absent is changed
+ - nm_web_esg_0_absent.current == []
+ - nm_web_esg_0_absent.previous | length == 1
+ - nm_web_esg_0_absent.previous.0.fvESg.attributes.name == 'web_esg_0'
+
+ - name: Remove an ESG with normal mode - idempotency works
+ cisco.aci.aci_esg:
+ <<: *nm_web_esg_0_absent
+ register: idempotency_web_esg_0_absent
+
+ - name: Idempotency assertions check for remove an ESG with normal mode
+ assert:
+ that:
+ - idempotency_web_esg_0_absent is not changed
+ - idempotency_web_esg_0_absent.current == []
+ - idempotency_web_esg_0_absent.previous == []
+
+ # Cleanup part
+ - name: Remove ap - application profile
+ cisco.aci.aci_ap:
+ <<: *anstest_ap_present
+ state: absent
+
+ - name: Remove ansible_test - tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml
new file mode 100644
index 000000000..debc3ec47
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_contract_master/tasks/main.yml
@@ -0,0 +1,218 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_password }}'
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+- name: Query system information
+ cisco.aci.aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Ensure tenant - ansible_test does not exists before testing
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+
+- name: Execute tasks only for ACI v5+ and non-cloud sites
+ when:
+ - version.current.0.topSystem.attributes.version is version('5', '>=')
+ - query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ # Setup part
+ - name: Ensure ansible_test - tenant exists
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Ensure ap - application profile exists
+ cisco.aci.aci_ap: &anstest_ap_present
+ <<: *tenant_present
+ ap: anstest_ap
+ state: present
+
+ - name: Ensure contract_master_ap - application profile exists
+ cisco.aci.aci_ap: &contract_master_ap_present
+ <<: *tenant_present
+ ap: contract_master_ap
+ state: present
+
+ - name: Ensure web_esg - endpoint security group exists
+ cisco.aci.aci_esg: &web_esg_present
+ <<: *anstest_ap_present
+ esg: web_esg
+ vrf: default
+ state: present
+
+ - name: Ensure contract_esg - endpoint security group exists
+ cisco.aci.aci_esg: &contract_esg_present
+ <<: *contract_master_ap_present
+ esg: contract_esg
+ vrf: default
+ state: present
+
+ # Test Part
+ - name: Add an ESG contract master to web_esg with check mode
+ cisco.aci.aci_esg_contract_master: &cm_contract_esg_present
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ esg: web_esg
+ contract_master_ap: contract_master_ap
+ contract_master_esg: contract_esg
+ state: present
+ check_mode: true
+ register: cm_contract_esg_present
+
+ - name: Assertions check for add an ESG contract master to web_esg with check mode
+ assert:
+ that:
+ - cm_contract_esg_present is changed
+ - cm_contract_esg_present.current == []
+ - cm_contract_esg_present.previous == []
+ - cm_contract_esg_present.sent.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+ - cm_contract_esg_present.sent.fvRsSecInherited.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add an ESG contract master to web_esg with normal mode
+ cisco.aci.aci_esg_contract_master: &nm_contract_esg_present
+ <<: *cm_contract_esg_present
+ register: nm_contract_esg_present
+
+ - name: Assertions check for add an ESG contract master to web_esg with normal mode
+ assert:
+ that:
+ - nm_contract_esg_present is changed
+ - nm_contract_esg_present.current | length == 1
+ - nm_contract_esg_present.previous == []
+ - nm_contract_esg_present.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+
+ - name: Add an ESG contract master to web_esg with normal mode - Idempotency works
+ cisco.aci.aci_esg_contract_master:
+ <<: *nm_contract_esg_present
+ register: idempotency_contract_esg_present
+
+ - name: Idempotency assertions check for add an ESG contract master to web_esg with normal mode
+ assert:
+ that:
+ - idempotency_contract_esg_present is not changed
+ - idempotency_contract_esg_present.current | length == 1
+ - idempotency_contract_esg_present.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+
+ - name: Query an ESG contract master
+ cisco.aci.aci_esg_contract_master:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ esg: web_esg
+ contract_master_ap: contract_master_ap
+ contract_master_esg: contract_esg
+ state: query
+ register: query_result_contract_master_esg
+
+ - name: Assertions check for query an ESG contract master
+ assert:
+ that:
+ - query_result_contract_master_esg is not changed
+ - query_result_contract_master_esg.current | length == 1
+ - query_result_contract_master_esg.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+
+ - name: Query an ESG contract master
+ cisco.aci.aci_esg_contract_master:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ esg: web_esg
+ state: query
+ register: query_all_contract_master
+
+ - name: Assertions check for query_all_contract_master
+ assert:
+ that:
+ - query_all_contract_master is not changed
+ - query_all_contract_master.current | length == 1
+ - query_all_contract_master.current.0.fvESg.children.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+
+ - name: Remove an ESG contract master with check mode
+ cisco.aci.aci_esg_contract_master: &cm_contract_esg_absent
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ esg: web_esg
+ contract_master_ap: contract_master_ap
+ contract_master_esg: contract_esg
+ state: absent
+ check_mode: true
+ register: cm_contract_esg_absent
+
+ - name: Assertions check for remove an ESG contract master with check mode
+ assert:
+ that:
+ - cm_contract_esg_absent is changed
+ - cm_contract_esg_absent.current != []
+ - cm_contract_esg_absent.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+ - cm_contract_esg_absent.previous | length == 1
+ - cm_contract_esg_absent.previous.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+
+ - name: Remove an ESG contract master with normal mode
+ cisco.aci.aci_esg_contract_master: &nm_contract_esg_absent
+ <<: *cm_contract_esg_absent
+ register: nm_contract_esg_absent
+
+ - name: Assertions check for remove an ESG contract master with normal mode
+ assert:
+ that:
+ - nm_contract_esg_absent is changed
+ - nm_contract_esg_absent.current == []
+ - nm_contract_esg_absent.previous | length == 1
+ - nm_contract_esg_absent.previous.0.fvRsSecInherited.attributes.tDn == "uni/tn-ansible_test/ap-contract_master_ap/esg-contract_esg"
+
+ - name: Remove an ESG contract master with normal mode - Idempotency works
+ cisco.aci.aci_esg_contract_master:
+ <<: *nm_contract_esg_absent
+ register: idempotency_contract_esg_absent
+
+ - name: Idempotency assertions check for remove an ESG contract master with normal mode
+ assert:
+ that:
+ - idempotency_contract_esg_absent is not changed
+ - idempotency_contract_esg_absent.current == []
+ - idempotency_contract_esg_absent.previous == []
+
+ # Cleanup part
+ - name: Remove web_esg - endpoint security group
+ cisco.aci.aci_esg:
+ <<: *web_esg_present
+ state: absent
+
+ - name: Remove ap - application profile
+ cisco.aci.aci_ap:
+ <<: *anstest_ap_present
+ state: absent
+
+ - name: Remove ansible_test - tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_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_esg_epg_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/tasks/main.yml
new file mode 100644
index 000000000..599828ae7
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_epg_selector/tasks/main.yml
@@ -0,0 +1,250 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Ensure tenant - ansible_test does not exists before testing
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+
+- name: Execute tasks only for ACI v5.2+ and non-cloud sites
+ when:
+ - version.current.0.topSystem.attributes.version is version('5.2', '>=')
+ - query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ # Setup part
+ - name: Ensure ansible_test - tenant exists
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Ensure ap - application profile exists
+ cisco.aci.aci_ap: &anstest_ap_present
+ <<: *tenant_present
+ ap: anstest_ap
+ state: present
+
+ - name: Ensure web_esg - endpoint security group exists
+ cisco.aci.aci_esg: &web_esg_present
+ <<: *anstest_ap_present
+ esg: web_esg
+ vrf: default
+ state: present
+
+ - name: Ensure epg_ap - application profile exists under the same tenant
+ cisco.aci.aci_ap: &epg_ap_present
+ <<: *tenant_present
+ ap: epg_ap
+ state: present
+
+ - name: Ensure anstest_epg - exists under epg_ap - application profile
+ cisco.aci.aci_epg:
+ <<: *epg_ap_present
+ epg: anstest_epg
+ bd: default
+ description: Ansible Test
+
+ - name: Add an EPG selector with check mode
+ cisco.aci.aci_esg_epg_selector: &cm_epg_selector_present
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ esg: web_esg
+ epg_ap: epg_ap
+ epg: anstest_epg
+ description: Ans Test EPG Selector
+ state: present
+ check_mode: true
+ register: cm_epg_selector_present
+
+ - name: Assertions check for add an EPG selector with check mode
+ assert:
+ that:
+ - cm_epg_selector_present is changed
+ - cm_epg_selector_present.current | length == 0
+ - cm_epg_selector_present.sent.fvEPgSelector.attributes.matchEpgDn == "uni/tn-ansible_test/ap-epg_ap/epg-anstest_epg"
+ - cm_epg_selector_present.sent.fvEPgSelector.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add an EPG selector with normal mode
+ cisco.aci.aci_esg_epg_selector:
+ <<: *cm_epg_selector_present
+ register: nm_epg_selector_present
+
+ - name: Assertions check for add an EPG selector with normal mode
+ assert:
+ that:
+ - nm_epg_selector_present is changed
+ - nm_epg_selector_present.current | length == 1
+ - nm_epg_selector_present.current.0.fvEPgSelector.attributes.matchEpgDn == "uni/tn-ansible_test/ap-epg_ap/epg-anstest_epg"
+
+ - name: Add an EPG selector with check mode - idempotency works
+ cisco.aci.aci_esg_epg_selector: &cm_idempotency_epg_selector_present
+ <<: *cm_epg_selector_present
+ check_mode: true
+ register: cm_idempotency_epg_selector_present
+
+ - name: Idempotency assertions check for add an EPG selector with check mode
+ assert:
+ that:
+ - cm_idempotency_epg_selector_present is not changed
+ - cm_idempotency_epg_selector_present.current | length == 1
+
+ - name: Add an EPG selector with normal mode - idempotency works
+ cisco.aci.aci_esg_epg_selector:
+ <<: *cm_idempotency_epg_selector_present
+ register: nm_idempotency_epg_selector_present
+
+ - name: Idempotency assertions check for add an EPG selector with normal mode
+ assert:
+ that:
+ - nm_idempotency_epg_selector_present is not changed
+ - nm_idempotency_epg_selector_present.current | length == 1
+
+ - name: Query a EPG selector with esg and epg name
+ cisco.aci.aci_esg_epg_selector:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ esg: web_esg
+ epg_ap: epg_ap
+ epg: anstest_epg
+ state: query
+ register: query_single_epg_selector
+
+ - name: Assertions check for query an EPG selector with esg and epg name
+ assert:
+ that:
+ - query_single_epg_selector is not changed
+ - query_single_epg_selector.current | length == 1
+ - query_single_epg_selector.current.0.fvEPgSelector.attributes.matchEpgDn == "uni/tn-ansible_test/ap-epg_ap/epg-anstest_epg"
+ - query_single_epg_selector.current.0.fvEPgSelector.attributes.descr == "Ans Test EPG Selector"
+
+ - name: Query all EPG selectors under an application profile
+ cisco.aci.aci_esg_epg_selector:
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ state: query
+ register: query_all_epg_selectors_under_ap
+
+ - name: Assertions check for query all EPG selectors under an application profile
+ assert:
+ that:
+ - query_all_epg_selectors_under_ap is not changed
+ - query_all_epg_selectors_under_ap.current | length == 1
+ - query_all_epg_selectors_under_ap.current.0.fvAp.attributes.name == 'anstest_ap'
+ - query_all_epg_selectors_under_ap.current.0.fvAp.children.0.fvESg.attributes.name == 'web_esg'
+ - query_all_epg_selectors_under_ap.current.0.fvAp.children.0.fvESg.children[0].fvEPgSelector.attributes.matchEpgDn == "uni/tn-ansible_test/ap-epg_ap/epg-anstest_epg"
+
+ - name: Query all EPG selectors
+ cisco.aci.aci_esg_epg_selector:
+ <<: *aci_info
+ state: query
+ register: query_all_epg_selectors
+
+ - name: Assertions check for query all EPG selectors
+ assert:
+ that:
+ - query_all_epg_selectors is not changed
+ - query_all_epg_selectors.current | length >= 1
+
+ - name: Remove an EPG selector with check mode
+ cisco.aci.aci_esg_epg_selector: &cm_epg_selector_absent
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest_ap
+ esg: web_esg
+ epg_ap: epg_ap
+ epg: anstest_epg
+ state: absent
+ check_mode: true
+ register: cm_epg_selector_absent
+
+ - name: Assertions check for remove an EPG selector with check mode
+ assert:
+ that:
+ - cm_epg_selector_absent is changed
+ - cm_epg_selector_absent.current != []
+ - cm_epg_selector_absent.current.0.fvEPgSelector.attributes.matchEpgDn == "uni/tn-ansible_test/ap-epg_ap/epg-anstest_epg"
+ - cm_epg_selector_absent.previous.0.fvEPgSelector.attributes.matchEpgDn == "uni/tn-ansible_test/ap-epg_ap/epg-anstest_epg"
+
+ - name: Remove an EPG selector with normal mode
+ cisco.aci.aci_esg_epg_selector:
+ <<: *cm_epg_selector_absent
+ register: nm_epg_selector_absent
+
+ - name: Assertions check for remove an EPG selector with normal mode
+ assert:
+ that:
+ - nm_epg_selector_absent is changed
+ - nm_epg_selector_absent.current == []
+ - nm_epg_selector_absent.previous.0.fvEPgSelector.attributes.matchEpgDn == "uni/tn-ansible_test/ap-epg_ap/epg-anstest_epg"
+
+ - name: Remove a EPG selector with check mode - idempotency works
+ cisco.aci.aci_esg_epg_selector: &cm_idempotency_epg_selector_absent
+ <<: *cm_epg_selector_absent
+ check_mode: true
+ register: cm_idempotency_epg_selector_absent
+
+ - name: Idempotency assertions check for EPG selector with check mode
+ assert:
+ that:
+ - cm_idempotency_epg_selector_absent is not changed
+ - cm_idempotency_epg_selector_absent.current == []
+
+ - name: Remove a EPG selector with normal mode - idempotency works
+ cisco.aci.aci_esg_epg_selector:
+ <<: *cm_idempotency_epg_selector_absent
+ register: nm_idempotency_epg_selector_absent
+
+ - name: Idempotency assertions check for EPG selector with normal mode
+ assert:
+ that:
+ - nm_idempotency_epg_selector_absent is not changed
+ - nm_idempotency_epg_selector_absent.current == []
+
+ # Cleanup part
+ - name: Remove web_esg - endpoint security group
+ cisco.aci.aci_esg:
+ <<: *web_esg_present
+ state: absent
+
+ - name: Remove ap - application profile
+ cisco.aci.aci_ap:
+ <<: *anstest_ap_present
+ state: absent
+
+ - name: Remove ansible_test - tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_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_esg_ip_subnet_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml
new file mode 100644
index 000000000..f96391704
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_ip_subnet_selector/tasks/main.yml
@@ -0,0 +1,181 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Ensure tenant - ansible_test does not exists before testing
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+
+- name: Execute tasks only for ACI v5+ and non-cloud sites
+ when:
+ - version.current.0.topSystem.attributes.version is version('5', '>=')
+ - query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ # Setup part
+ - name: Ensure ansible_test - tenant exists
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Ensure ap - application profile exists
+ cisco.aci.aci_ap: &anstest_ap_present
+ <<: *tenant_present
+ ap: anstest_ap
+ state: present
+
+ - name: Ensure web_esg - endpoint security group exists
+ cisco.aci.aci_esg: &web_esg_present
+ <<: *anstest_ap_present
+ esg: web_esg
+ vrf: default
+ state: present
+
+ # Test Part
+ - name: Add IP Subnet selector with check mode
+ cisco.aci.aci_esg_ip_subnet_selector: &cm_subnet_ip_present
+ <<: *aci_info
+ <<: *web_esg_present
+ vrf: "{{ fake_var | default(omit) }}"
+ ip: "10.0.0.1"
+ description: "IP Subnet Selector"
+ state: present
+ check_mode: true
+ register: cm_subnet_ip_present
+
+ - name: Assertions check for add IP Subnet selector with check mode
+ assert:
+ that:
+ - cm_subnet_ip_present is changed
+ - cm_subnet_ip_present.current == []
+ - cm_subnet_ip_present.previous == []
+ - cm_subnet_ip_present.sent.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+
+ - name: Add IP Subnet selector with normal mode
+ cisco.aci.aci_esg_ip_subnet_selector: &nm_subnet_ip_present
+ <<: *cm_subnet_ip_present
+ register: nm_subnet_ip_present
+
+ - name: Assertions check for add IP Subnet selector with normal mode
+ assert:
+ that:
+ - nm_subnet_ip_present is changed
+ - nm_subnet_ip_present.current | length == 1
+ - nm_subnet_ip_present.current.0.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+ - nm_subnet_ip_present.current.0.fvEPSelector.attributes.dn == "uni/tn-ansible_test/ap-anstest_ap/esg-web_esg/epselector-[ip=='10.0.0.1']"
+ - nm_subnet_ip_present.current.0.fvEPSelector.attributes.annotation == 'orchestrator:ansible'
+ - nm_subnet_ip_present.previous == []
+ - nm_subnet_ip_present.sent.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+
+ - name: Add IP Subnet selector with normal mode - idempotency works
+ cisco.aci.aci_esg_ip_subnet_selector:
+ <<: *nm_subnet_ip_present
+ register: idempotency_nm_subnet_ip_present
+
+ - name: Idempotency assertions check for add IP Subnet selectors with normal mode
+ assert:
+ that:
+ - idempotency_nm_subnet_ip_present is not changed
+ - idempotency_nm_subnet_ip_present.current.0.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+ - idempotency_nm_subnet_ip_present.current.0.fvEPSelector.attributes.descr == "IP Subnet Selector"
+ - idempotency_nm_subnet_ip_present.previous.0.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+ - idempotency_nm_subnet_ip_present.proposed.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+
+ - name: Query all IP Subnet selectors
+ cisco.aci.aci_esg_ip_subnet_selector:
+ <<: *aci_info
+ state: query
+ register: query_result
+
+ - name: Assertions check for query all IP Subnet selectors
+ assert:
+ that:
+ - query_result is not changed
+ - query_result.current | length >= 1
+
+ - name: Remove IP Subnet selector with check mode
+ cisco.aci.aci_esg_ip_subnet_selector: &cm_subnet_ip_absent
+ <<: *cm_subnet_ip_present
+ state: absent
+ check_mode: true
+ register: cm_subnet_ip_absent
+
+ - name: Assertions check for remove IP Subnet selector with check mode
+ assert:
+ that:
+ - cm_subnet_ip_absent is changed
+ - cm_subnet_ip_absent.current != []
+ - cm_subnet_ip_absent.previous.0.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+ - cm_subnet_ip_absent.previous.0.fvEPSelector.attributes.descr == "IP Subnet Selector"
+ - cm_subnet_ip_absent.current.0.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+ - cm_subnet_ip_absent.current.0.fvEPSelector.attributes.descr == "IP Subnet Selector"
+
+ - name: Remove IP Subnet selector with normal mode
+ cisco.aci.aci_esg_ip_subnet_selector: &nm_subnet_ip_absent
+ <<: *cm_subnet_ip_absent
+ register: nm_subnet_ip_absent
+
+ - name: Assertions check for remove IP Subnet selector with normal mode
+ assert:
+ that:
+ - nm_subnet_ip_absent is changed
+ - nm_subnet_ip_absent.current == []
+ - nm_subnet_ip_absent.previous.0.fvEPSelector.attributes.matchExpression == "ip=='10.0.0.1'"
+ - nm_subnet_ip_absent.previous.0.fvEPSelector.attributes.descr == "IP Subnet Selector"
+
+ - name: Remove IP Subnet selector with normal mode - idempotency works
+ cisco.aci.aci_esg_ip_subnet_selector:
+ <<: *nm_subnet_ip_absent
+ register: idempotency_nm_subnet_ip_absent
+
+ - name: Idempotency assertions check for remove IP Subnet selector with normal mode
+ assert:
+ that:
+ - idempotency_nm_subnet_ip_absent is not changed
+ - idempotency_nm_subnet_ip_absent.current == []
+
+ # Cleanup part
+ - name: Remove web_esg - endpoint security group
+ cisco.aci.aci_esg:
+ <<: *web_esg_present
+ state: absent
+
+ - name: Remove ap - application profile
+ cisco.aci.aci_ap:
+ <<: *anstest_ap_present
+ state: absent
+
+ - name: Remove ansible_test - tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_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_esg_tag_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml
new file mode 100644
index 000000000..5df3b0754
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_esg_tag_selector/tasks/main.yml
@@ -0,0 +1,188 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Ensure tenant - ansible_test does not exists before testing
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ output_level: debug
+ tenant: ansible_test
+ state: absent
+
+- name: Execute tasks only for ACI v5.2+ and non-cloud sites
+ when:
+ - version.current.0.topSystem.attributes.version is version('5.2', '>=')
+ - query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ # Setup part
+ - name: Ensure ansible_test - tenant exists
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Ensure ap - application profile exists
+ cisco.aci.aci_ap: &anstest_ap_present
+ <<: *tenant_present
+ ap: anstest_ap
+ state: present
+
+ - name: Ensure web_esg - endpoint security group exists
+ cisco.aci.aci_esg: &web_esg_present
+ <<: *anstest_ap_present
+ esg: web_esg
+ vrf: default
+ state: present
+
+ # Test Part
+ - name: Add a tag selector under web_esg with name and value(check_mode)
+ cisco.aci.aci_esg_tag_selector: &selector_0_cm_present
+ <<: *anstest_ap_present
+ esg: web_esg
+ name: tag-selector-0
+ match_value: tag-value-0
+ description: tag-selector-description
+ state: present
+ register: selector_0_cm_present
+ check_mode: true
+
+ - name: Add a tag selector under web_esg with name and value(normal_mode)
+ cisco.aci.aci_esg_tag_selector:
+ <<: *selector_0_cm_present
+ register: selector_0_nm_present
+
+ - name: present assertions for Tag Selector - tag-selector-0
+ assert:
+ that:
+ - selector_0_cm_present is changed
+ - selector_0_nm_present is changed
+ - selector_0_cm_present.sent.fvTagSelector.attributes.matchKey == 'tag-selector-0'
+ - selector_0_cm_present.sent.fvTagSelector.attributes.matchValue == 'tag-value-0'
+ - selector_0_nm_present.current.0.fvTagSelector.attributes.matchKey == 'tag-selector-0'
+ - selector_0_nm_present.current.0.fvTagSelector.attributes.matchValue == 'tag-value-0'
+ - selector_0_nm_present.current.0.fvTagSelector.attributes.valueOperator == 'equals'
+ - selector_0_nm_present.current.0.fvTagSelector.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Query all Tag Selectors
+ cisco.aci.aci_esg_tag_selector:
+ <<: *aci_info
+ state: query
+ register: query_result
+
+ - name: Verification of query all Tag Selectors - query_result
+ assert:
+ that:
+ - query_result is not changed
+ - query_result.current | length >= 1
+
+ - name: Query all Tag Selectors with a name and value
+ cisco.aci.aci_esg_tag_selector:
+ <<: *aci_info
+ name: tag-selector-0
+ match_value: tag-value-0
+ state: query
+ register: result_with_name_and_value
+
+ - name: Verification of query - Tag Selectors with a name and value
+ assert:
+ that:
+ - result_with_name_and_value is not changed
+ - result_with_name_and_value.current | length == 1
+ - result_with_name_and_value.current.0.fvTagSelector.attributes.matchKey == 'tag-selector-0'
+ - result_with_name_and_value.current.0.fvTagSelector.attributes.matchValue == 'tag-value-0'
+ - result_with_name_and_value.current.0.fvTagSelector.attributes.valueOperator == 'equals'
+
+ - name: Query all Tag Selectors with only name
+ cisco.aci.aci_esg_tag_selector:
+ <<: *aci_info
+ name: tag-selector-0
+ state: query
+ register: result_with_name
+
+ - name: Verification of query - Tag Selectors with only name
+ assert:
+ that:
+ - result_with_name is not changed
+ - result_with_name.current | length == 1
+ - result_with_name.current.0.fvTagSelector.attributes.matchKey == 'tag-selector-0'
+ - result_with_name.current.0.fvTagSelector.attributes.matchValue == 'tag-value-0'
+ - result_with_name.current.0.fvTagSelector.attributes.valueOperator == 'equals'
+
+ - name: Remove a Tag Selector with name and value(check_mode)
+ cisco.aci.aci_esg_tag_selector: &selector_0_cm_absent_with_name_and_value
+ <<: *anstest_ap_present
+ esg: web_esg
+ name: tag-selector-0
+ match_value: tag-value-0
+ state: absent
+ register: selector_0_cm_absent_with_name_and_value
+ check_mode: true
+
+ - name: Remove a Tag Selector with name and value(normal_mode)
+ cisco.aci.aci_esg_tag_selector:
+ <<: *selector_0_cm_absent_with_name_and_value
+ register: selector_0_nm_absent_with_name_and_value
+
+ - name: Verification of selector_0_nm_absent_with_name - Tag Selectors under web_esg
+ assert:
+ that:
+ - selector_0_cm_absent_with_name_and_value is changed
+ - selector_0_cm_absent_with_name_and_value.current | length == 1
+ - selector_0_nm_absent_with_name_and_value is changed
+ - selector_0_nm_absent_with_name_and_value.current | length == 0
+ - selector_0_nm_absent_with_name_and_value.previous.0.fvTagSelector.attributes.matchKey == 'tag-selector-0'
+ - selector_0_nm_absent_with_name_and_value.previous.0.fvTagSelector.attributes.matchValue == 'tag-value-0'
+
+ - name: Remove a Tag Selector with name and value(normal_mode) - idempotency works
+ cisco.aci.aci_esg_tag_selector:
+ <<: *selector_0_cm_absent_with_name_and_value
+ register: idempotency_selector_0_nm_absent_with_name_and_value
+
+ - name: Verification of idempotency_selector_0_nm_absent_with_name_and_value - Tag Selectors under web_esg
+ assert:
+ that:
+ - idempotency_selector_0_nm_absent_with_name_and_value is not changed
+ - idempotency_selector_0_nm_absent_with_name_and_value.current | length == 0
+
+ # Cleanup part
+ - name: Remove web_esg - endpoint security group
+ cisco.aci.aci_esg:
+ <<: *web_esg_present
+ state: absent
+
+ - name: Remove ap - application profile
+ cisco.aci.aci_ap:
+ <<: *anstest_ap_present
+ state: absent
+
+ - name: Remove ansible_test - tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_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_fabric_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml
new file mode 100644
index 000000000..d4bf60dd5
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_profile/tasks/main.yml
@@ -0,0 +1,122 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_leaf_switch_prf if it already exists
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
+
+# CREATE SPINE SWITCH POLICY
+- name: Create ansible_leaf_switch_prf
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: present
+ register: add_switch_prf
+
+- name: Verify profile creation
+ assert:
+ that:
+ - add_switch_prf.current.0.fabricLeafP.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf"
+ - add_switch_prf.current.0.fabricLeafP.attributes.name == "ansible_leaf_switch_prf"
+ - add_switch_prf.current.0.fabricLeafP.attributes.annotation == 'orchestrator:ansible'
+
+# CREATE SPINE SWITCH POLICY AGAIN TO TEST IDEMPOTENCE
+- name: Create ansible_leaf_switch_prf again
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: present
+ register: add_switch_prf_again
+
+- name: Verify profile creation idempotence
+ assert:
+ that:
+ - add_switch_prf_again is not changed
+ - add_switch_prf_again.current.0.fabricLeafP.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf"
+ - add_switch_prf_again.current.0.fabricLeafP.attributes.name == "ansible_leaf_switch_prf"
+
+# QUERY SPINE SWITCH POLICY
+- name: query leaf switch profile
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: query
+ register: query_switch_prf
+
+- name: Verify profile query
+ assert:
+ that:
+ - query_switch_prf is not changed
+ - query_switch_prf.current.0.fabricLeafP.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf"
+ - query_switch_prf.current.0.fabricLeafP.attributes.name == "ansible_leaf_switch_prf"
+
+# QUERY ALL SPINE SWITCH POLICIES
+- name: query all leaf switch profiles
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ state: query
+ register: query_switch_prf_all
+
+- name: Verify profile query idempotence
+ assert:
+ that:
+ - query_switch_prf_all is not changed
+
+# DELETE SPINE SWITCH PROFILE
+- name: Delete ansible_leaf_switch_prf
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
+ register: delete_switch_prf
+
+- name: Verify profile deletion
+ assert:
+ that:
+ - delete_switch_prf is changed
+ - delete_switch_prf.current == []
+ - delete_switch_prf.previous.0.fabricLeafP.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf"
+ - delete_switch_prf.previous.0.fabricLeafP.attributes.name == "ansible_leaf_switch_prf"
+
+# DELETE SPINE SWITCH PROFILE AGAIN TO TEST IDEMPOTENCE
+- name: Delete ansible_leaf_switch_prf again
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
+ register: delete_switch_prf_again
+
+- name: Verify profile deletion idempotence
+ assert:
+ that:
+ - delete_switch_prf_again is not changed
+ - delete_switch_prf_again.current == []
+
+# CLEAN UP ENVIRONMENT
+- name: Remove ansible_leaf_switch_prf
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/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_leaf_switch_assoc/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml
new file mode 100644
index 000000000..35caafdb3
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_leaf_switch_assoc/tasks/main.yml
@@ -0,0 +1,194 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_leaf_switch_prf if it already exists
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
+
+# CREATE SPINE SWITCH POLICY
+- name: Create ansible_leaf_switch_prf
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: present
+
+# CREATE SPINE SWITCH ASSOCIATION
+- name: Create a leaf switch profile association
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc
+ policy_group: ansible_leaf_pol_grp1
+ state: present
+ register: add_association
+
+- name: Verify association creation
+ assert:
+ that:
+ - add_association.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range"
+ - add_association.current.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc"
+ - add_association.current.0.fabricLeafS.attributes.type == "range"
+ - add_association.current.0.fabricLeafS.attributes.annotation == 'orchestrator:ansible'
+
+- name: Verify Policy Group association
+ assert:
+ that:
+ - add_association.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp1"
+
+# CREATE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE
+- name: Create a leaf switch profile association again
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc
+ policy_group: ansible_leaf_pol_grp1
+ state: present
+ register: add_association_again
+
+- name: Verify association creation idempotence
+ assert:
+ that:
+ - add_association_again is not changed
+ - add_association_again.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range"
+ - add_association_again.current.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc"
+ - add_association_again.current.0.fabricLeafS.attributes.type == "range"
+
+- name: Verify Policy Group association idempotence
+ assert:
+ that:
+ - add_association_again.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp1"
+
+# CREATE SPINE SWITCH ASSOCIATION WITHOUT POLICY GROUP
+- name: Create a leaf switch profile association without a policy group
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc2
+ state: present
+ register: add_association_without_policy_group
+
+- name: Verify association creation
+ assert:
+ that:
+ - add_association_without_policy_group.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc2-typ-range"
+ - add_association_without_policy_group.current.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc2"
+ - add_association_without_policy_group.current.0.fabricLeafS.attributes.type == "range"
+
+# UPDATE SPINE SWITCH POLICY GROUP ASSOCIATION
+- name: Update a leaf switch profile association
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc
+ policy_group: ansible_leaf_pol_grp2
+ state: present
+ register: update_association
+
+- name: Verify association update
+ assert:
+ that:
+ - update_association is changed
+ - update_association.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range"
+ - update_association.current.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc"
+ - update_association.current.0.fabricLeafS.attributes.type == "range"
+
+- name: Verify Policy Group association update
+ assert:
+ that:
+ - update_association.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp2"
+
+# QUERY SPINE SWITCH ASSOCIATION
+- name: Query leaf switch profile association
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc
+ state: query
+ register: query_association
+
+- name: Verify query data
+ assert:
+ that:
+ - query_association is not changed
+ - query_association.current.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range"
+ - query_association.current.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc"
+ - query_association.current.0.fabricLeafS.attributes.type == "range"
+
+- name: Verify Policy Group association
+ assert:
+ that:
+ - query_association.current.0.fabricLeafS.children.0.fabricRsLeNodePGrp.attributes.tDn == "uni/fabric/funcprof/lenodepgrp-ansible_leaf_pol_grp2"
+
+# QUERY ALL SPINE SWITCH ASSOCIATIONS
+- name: Query leaf switch profile association
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ state: query
+ register: query_association_all
+
+- name: Verify query all idempotence
+ assert:
+ that:
+ - query_association_all is not changed
+
+# DELETE SPINE SWITCH ASSOCIATION
+- name: Delete leaf switch profile association
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc
+ state: absent
+ register: delete_association
+
+- name: Verify association removal
+ assert:
+ that:
+ - delete_association is changed
+ - delete_association.current == []
+ - delete_association.previous.0.fabricLeafS.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range"
+ - delete_association.previous.0.fabricLeafS.attributes.name == "ansible_leaf_switch_assoc"
+ - delete_association.previous.0.fabricLeafS.attributes.type == "range"
+
+# DELETE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE
+- name: Delete leaf switch profile association again
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc
+ state: absent
+ register: delete_association_again
+
+- name: Verify association removal idempotence
+ assert:
+ that:
+ - delete_association_again is not changed
+ - delete_association_again.current == []
+
+# CLEAN UP ENVIRONMENT
+- name: Remove ansible_leaf_switch_prf
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_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_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml
new file mode 100644
index 000000000..36e065e5b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml
@@ -0,0 +1,218 @@
+# Test code for the ACI modules
+# 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)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+
+# CLEAN ENVIRONMENT
+- name: 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") }}'
+ serial: ansible_test
+ node_id: 105
+ state: absent
+
+
+# ADD FABRIC NODE
+- name: Add fabric node (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
+ switch: anstest
+ state: present
+ check_mode: true
+ register: cm_add_fabric_node
+
+- name: Add fabric node (normal mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_present
+ register: nm_add_fabric_node
+
+- name: Add fabric node again (check_mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_present
+ check_mode: true
+ register: cm_add_fabric_node_again
+
+- name: Add fabric node again (normal mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_present
+ register: nm_add_fabric_node_again
+
+- name: Verify add_fabric_node
+ assert:
+ that:
+ - cm_add_fabric_node is changed
+ - nm_add_fabric_node is changed
+ - nm_add_fabric_node.current.0.fabricNodeIdentP.attributes.annotation == 'orchestrator:ansible'
+ # FIXME: Module is not idempotent
+ - cm_add_fabric_node_again is not changed
+ - nm_add_fabric_node_again is not changed
+
+
+# CHANGE FABRIC NODE
+- name: Change description of fabric node (check_mode)
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_present
+ description: Ansible test fabric node
+ check_mode: true
+ register: cm_add_fabric_node_descr
+
+- name: Change description of fabric node (normal mode)
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_present
+ description: Ansible test fabric node
+ register: nm_add_fabric_node_descr
+
+- name: Change description of fabric nodeagain (check_mode)
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_present
+ description: Ansible test fabric node
+ check_mode: true
+ register: cm_add_fabric_node_descr_again
+
+- name: Change description of fabric node again (normal mode)
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_present
+ description: Ansible test fabric node
+ register: nm_add_fabric_node_descr_again
+
+- name: Verify add_fabric_node_descr
+ assert:
+ that:
+ - cm_add_fabric_node_descr is changed
+ - nm_add_fabric_node_descr is changed
+ # FIXME: Module is not idempotent
+ - cm_add_fabric_node_descr_again is not changed
+ - nm_add_fabric_node_descr_again is not changed
+
+
+# ADD FABRIC NODE AGAIN
+- name: Add fabric node again with no description (check_mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_present
+ check_mode: true
+ register: cm_add_fabric_node_again_no_descr
+
+- name: Add fabric node again with no description (normal mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_present
+ register: nm_add_fabric_node_again_no_descr
+
+- name: Verify add_fabric_node_again_no_descr
+ assert:
+ that:
+ # FIXME: Module is not idempotent
+ - cm_add_fabric_node_again_no_descr is not changed
+ - nm_add_fabric_node_again_no_descr is not changed
+
+
+# QUERY ALL FABRIC NODES
+- name: Query fabric nodes (check_mode)
+ cisco.aci.aci_fabric_node: &aci_fabric_node_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_fabric_nodes
+
+- name: Query all fabric nodes (normal mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_query
+ register: nm_query_all_fabric_nodes
+
+- name: Verify query_all_fabric_nodes
+ assert:
+ that:
+ - cm_query_all_fabric_nodes is not changed
+ - nm_query_all_fabric_nodes is not changed
+ - cm_query_all_fabric_nodes == nm_query_all_fabric_nodes
+
+
+# QUERY A FABRIC NODE
+- name: Query our fabric_node
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_query
+ serial: ansible_test # might need node_id too
+ check_mode: true
+ register: cm_query_fabric_node
+
+- name: Query our fabric_node
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_query
+ serial: ansible_test
+ register: nm_query_fabric_node
+
+- name: Verify query_fabric_node
+ assert:
+ that:
+ - cm_query_fabric_node is not changed
+ - nm_query_fabric_node is not changed
+ - cm_query_fabric_node == nm_query_fabric_node
+
+
+# REMOVE FABRIC NODE
+- name: Remove fabric_node (check_mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_absent
+ check_mode: true
+ register: cm_remove_fabric_node
+
+- name: Remove fabric_node (normal mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_absent
+ register: nm_remove_fabric_node
+
+- name: Remove fabric_node again (check_mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_absent
+ check_mode: true
+ register: cm_remove_fabric_node_again
+
+- name: Remove fabric_node again (normal mode)
+ cisco.aci.aci_fabric_node: *aci_fabric_node_absent
+ register: nm_remove_fabric_node_again
+
+- name: Verify remove_fabric_node
+ assert:
+ that:
+ - cm_remove_fabric_node is changed
+ - nm_remove_fabric_node is changed
+ - cm_remove_fabric_node_again is not changed
+ - nm_remove_fabric_node_again is not changed
+
+
+# QUERY NON-EXISTING LEAF PROFILE
+- name: Query non-existing fabric_node (check_mode)
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_query
+ serial: ansible_test
+ check_mode: true
+ register: cm_query_non_fabric_node
+
+- name: Query non-existing fabric_node (normal mode)
+ cisco.aci.aci_fabric_node:
+ <<: *aci_fabric_node_query
+ serial: ansible_test
+ register: nm_query_non_fabric_node
+
+- name: Verify query_non_fabric_node
+ assert:
+ that:
+ - cm_query_non_fabric_node is not changed
+ - nm_query_non_fabric_node is not changed
+ - cm_query_non_fabric_node == nm_query_non_fabric_node
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_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_pod_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml
new file mode 100644
index 000000000..282fe15d3
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_pod_policy_group/tasks/main.yml
@@ -0,0 +1,264 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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 any pre-existing pod policy group
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *aci_info
+ name: '{{ item }}'
+ state: absent
+ loop:
+ - "ansible_pod_policy_group"
+ - "ansible_empty_pod_policy_group"
+
+# ADD POD POLICY GROUP
+- name: Add pod policy group (check mode)
+ cisco.aci.aci_fabric_pod_policy_group: &group_present
+ <<: *aci_info
+ name: ansible_pod_policy_group
+ date_time_policy: default
+ isis_policy: default
+ coop_group_policy: default
+ bgp_rr_policy: default
+ management_access_policy: default
+ snmp_policy: default
+ macsec_policy: default
+ state: present
+ check_mode: true
+ register: cm_add_group
+
+- name: Add pod policy group (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_present
+ register: nm_add_group
+
+- name: Add pod policy group again (check mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_present
+ check_mode: true
+ register: cm_add_group_again
+
+- name: Add pod policy group again (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_present
+ register: nm_add_group_again
+
+- name: Verify add policy group
+ assert:
+ that:
+ - cm_add_group is changed
+ - nm_add_group is changed
+ - nm_add_group.current.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_pod_policy_group'
+ - nm_add_group.current.0.fabricPodPGrp.attributes.name == 'ansible_pod_policy_group'
+ - nm_add_group.current.0.fabricPodPGrp.children.0.fabricRsSnmpPol.attributes.tnSnmpPolName == 'default'
+ - nm_add_group.current.0.fabricPodPGrp.children.1.fabricRsPodPGrpCoopP.attributes.tnCoopPolName == 'default'
+ - nm_add_group.current.0.fabricPodPGrp.children.2.fabricRsCommPol.attributes.tnCommPolName == 'default'
+ - nm_add_group.current.0.fabricPodPGrp.children.3.fabricRsMacsecPol.attributes.tnMacsecFabIfPolName == 'default'
+ - nm_add_group.current.0.fabricPodPGrp.children.4.fabricRsTimePol.attributes.tnDatetimePolName == 'default'
+ - nm_add_group.current.0.fabricPodPGrp.children.5.fabricRsPodPGrpBGPRRP.attributes.tnBgpInstPolName == 'default'
+ - nm_add_group.current.0.fabricPodPGrp.children.6.fabricRsPodPGrpIsisDomP.attributes.tnIsisDomPolName == 'default'
+ - cm_add_group_again is not changed
+ - nm_add_group_again is not changed
+ - nm_add_group_again.current.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_pod_policy_group'
+ - nm_add_group_again.current.0.fabricPodPGrp.attributes.name == 'ansible_pod_policy_group'
+ - nm_add_group_again.current.0.fabricPodPGrp.children.0.fabricRsSnmpPol.attributes.tnSnmpPolName == 'default'
+ - nm_add_group_again.current.0.fabricPodPGrp.children.1.fabricRsPodPGrpCoopP.attributes.tnCoopPolName == 'default'
+ - nm_add_group_again.current.0.fabricPodPGrp.children.2.fabricRsCommPol.attributes.tnCommPolName == 'default'
+ - nm_add_group_again.current.0.fabricPodPGrp.children.3.fabricRsMacsecPol.attributes.tnMacsecFabIfPolName == 'default'
+ - nm_add_group_again.current.0.fabricPodPGrp.children.4.fabricRsTimePol.attributes.tnDatetimePolName == 'default'
+ - nm_add_group_again.current.0.fabricPodPGrp.children.5.fabricRsPodPGrpBGPRRP.attributes.tnBgpInstPolName == 'default'
+ - nm_add_group_again.current.0.fabricPodPGrp.children.6.fabricRsPodPGrpIsisDomP.attributes.tnIsisDomPolName == 'default'
+
+- name: Add empty pod policy group (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *aci_info
+ name: ansible_empty_pod_policy_group
+ state: present
+ register: nm_add_empty_group
+
+- name: Verify add empty policy group
+ assert:
+ that:
+ - nm_add_empty_group is changed
+ - nm_add_empty_group.current.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_empty_pod_policy_group'
+ - nm_add_empty_group.current.0.fabricPodPGrp.attributes.name == 'ansible_empty_pod_policy_group'
+ - nm_add_empty_group.current.0.fabricPodPGrp.children.0.fabricRsSnmpPol.attributes.tnSnmpPolName == ''
+ - nm_add_empty_group.current.0.fabricPodPGrp.children.1.fabricRsPodPGrpCoopP.attributes.tnCoopPolName == ''
+ - nm_add_empty_group.current.0.fabricPodPGrp.children.2.fabricRsCommPol.attributes.tnCommPolName == ''
+ - nm_add_empty_group.current.0.fabricPodPGrp.children.3.fabricRsMacsecPol.attributes.tnMacsecFabIfPolName == ''
+ - nm_add_empty_group.current.0.fabricPodPGrp.children.4.fabricRsTimePol.attributes.tnDatetimePolName == ''
+ - nm_add_empty_group.current.0.fabricPodPGrp.children.5.fabricRsPodPGrpBGPRRP.attributes.tnBgpInstPolName == ''
+ - nm_add_empty_group.current.0.fabricPodPGrp.children.6.fabricRsPodPGrpIsisDomP.attributes.tnIsisDomPolName == ''
+
+# MODIFY POLICY GROUP
+- name: Modify pod policy group (check mode)
+ cisco.aci.aci_fabric_pod_policy_group: &group_changed
+ <<: *aci_info
+ name: ansible_pod_policy_group
+ date_time_policy: ''
+ isis_policy: ''
+ coop_group_policy: ''
+ bgp_rr_policy: ''
+ management_access_policy: ''
+ snmp_policy: ''
+ macsec_policy: ''
+ state: present
+ check_mode: true
+ register: cm_modify_group
+
+- name: Modify pod policy group (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_changed
+ register: nm_modify_group
+
+- name: Modify policy group again (check mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_changed
+ check_mode: true
+ register: cm_modify_group_again
+
+- name: Modify policy group again (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_changed
+ register: nm_modify_group_again
+
+- name: Verify modify policy
+ assert:
+ that:
+ - cm_modify_group is changed
+ - nm_modify_group is changed
+ - nm_modify_group.current.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_pod_policy_group'
+ - nm_modify_group.current.0.fabricPodPGrp.attributes.name == 'ansible_pod_policy_group'
+ - nm_modify_group.current.0.fabricPodPGrp.children.0.fabricRsSnmpPol.attributes.tnSnmpPolName == ''
+ - nm_modify_group.current.0.fabricPodPGrp.children.1.fabricRsPodPGrpCoopP.attributes.tnCoopPolName == ''
+ - nm_modify_group.current.0.fabricPodPGrp.children.2.fabricRsCommPol.attributes.tnCommPolName == ''
+ - nm_modify_group.current.0.fabricPodPGrp.children.3.fabricRsMacsecPol.attributes.tnMacsecFabIfPolName == ''
+ - nm_modify_group.current.0.fabricPodPGrp.children.4.fabricRsTimePol.attributes.tnDatetimePolName == ''
+ - nm_modify_group.current.0.fabricPodPGrp.children.5.fabricRsPodPGrpBGPRRP.attributes.tnBgpInstPolName == ''
+ - nm_modify_group.current.0.fabricPodPGrp.children.6.fabricRsPodPGrpIsisDomP.attributes.tnIsisDomPolName == ''
+ - cm_modify_group_again is not changed
+ - nm_modify_group_again is not changed
+ - nm_modify_group_again.current.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_pod_policy_group'
+ - nm_modify_group_again.current.0.fabricPodPGrp.attributes.name == 'ansible_pod_policy_group'
+ - nm_modify_group_again.current.0.fabricPodPGrp.children.0.fabricRsSnmpPol.attributes.tnSnmpPolName == ''
+ - nm_modify_group_again.current.0.fabricPodPGrp.children.1.fabricRsPodPGrpCoopP.attributes.tnCoopPolName == ''
+ - nm_modify_group_again.current.0.fabricPodPGrp.children.2.fabricRsCommPol.attributes.tnCommPolName == ''
+ - nm_modify_group_again.current.0.fabricPodPGrp.children.3.fabricRsMacsecPol.attributes.tnMacsecFabIfPolName == ''
+ - nm_modify_group_again.current.0.fabricPodPGrp.children.4.fabricRsTimePol.attributes.tnDatetimePolName == ''
+ - nm_modify_group_again.current.0.fabricPodPGrp.children.5.fabricRsPodPGrpBGPRRP.attributes.tnBgpInstPolName == ''
+ - nm_modify_group_again.current.0.fabricPodPGrp.children.6.fabricRsPodPGrpIsisDomP.attributes.tnIsisDomPolName == ''
+
+# QUERY ALL POLICY GROUPS
+- name: Query all policy groups (check_mode)
+ cisco.aci.aci_fabric_pod_policy_group: &group_query_all
+ 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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_groups
+
+- name: Query all groups (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_query_all
+ register: nm_query_all_groups
+
+- name: Verify query_all_groups
+ assert:
+ that:
+ - cm_query_all_groups is not changed
+ - nm_query_all_groups is not changed
+
+# QUERY A POD POLICY GROUP
+- name: Query a specific pod policy (check_mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_query_all
+ name: ansible_pod_policy_group
+ check_mode: true
+ register: cm_query_group
+
+- name: Query a specific pod policy (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_query_all
+ name: ansible_pod_policy_group
+ register: nm_query_group
+
+- name: Verify query_group
+ assert:
+ that:
+ - cm_query_group is not changed
+ - nm_query_group is not changed
+ - cm_query_group == nm_query_group
+ - nm_query_group.current.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_pod_policy_group'
+ - nm_query_group.current.0.fabricPodPGrp.attributes.name == 'ansible_pod_policy_group'
+ - nm_query_group.current.0.fabricPodPGrp.children.0.fabricRsSnmpPol.attributes.tnSnmpPolName == ''
+ - nm_query_group.current.0.fabricPodPGrp.children.1.fabricRsPodPGrpCoopP.attributes.tnCoopPolName == ''
+ - nm_query_group.current.0.fabricPodPGrp.children.2.fabricRsCommPol.attributes.tnCommPolName == ''
+ - nm_query_group.current.0.fabricPodPGrp.children.3.fabricRsMacsecPol.attributes.tnMacsecFabIfPolName == ''
+ - nm_query_group.current.0.fabricPodPGrp.children.4.fabricRsTimePol.attributes.tnDatetimePolName == ''
+ - nm_query_group.current.0.fabricPodPGrp.children.5.fabricRsPodPGrpBGPRRP.attributes.tnBgpInstPolName == ''
+ - nm_query_group.current.0.fabricPodPGrp.children.6.fabricRsPodPGrpIsisDomP.attributes.tnIsisDomPolName == ''
+
+# REMOVE POLICY GROUP
+- name: Remove policy group (check mode)
+ cisco.aci.aci_fabric_pod_policy_group: &group_absent
+ <<: *group_present
+ state: absent
+ check_mode: true
+ register: cm_remove_group
+
+- name: Remove policy group (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_absent
+ register: nm_remove_group
+
+- name: Remove policy group again (check mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_absent
+ check_mode: true
+ register: cm_remove_group_again
+
+- name: Remove policy group again (normal mode)
+ cisco.aci.aci_fabric_pod_policy_group:
+ <<: *group_absent
+ register: nm_remove_group_again
+
+- name: Verify remove_group and remove_group_again
+ assert:
+ that:
+ - cm_remove_group is changed
+ - nm_remove_group is changed
+ - nm_remove_group.current == []
+ - nm_remove_group.previous.0.fabricPodPGrp.attributes.dn == 'uni/fabric/funcprof/podpgrp-ansible_pod_policy_group'
+ - nm_remove_group.previous.0.fabricPodPGrp.attributes.name == 'ansible_pod_policy_group'
+ - nm_remove_group.previous.0.fabricPodPGrp.children.0.fabricRsSnmpPol.attributes.tnSnmpPolName == ''
+ - nm_remove_group.previous.0.fabricPodPGrp.children.1.fabricRsPodPGrpCoopP.attributes.tnCoopPolName == ''
+ - nm_remove_group.previous.0.fabricPodPGrp.children.2.fabricRsCommPol.attributes.tnCommPolName == ''
+ - nm_remove_group.previous.0.fabricPodPGrp.children.3.fabricRsMacsecPol.attributes.tnMacsecFabIfPolName == ''
+ - nm_remove_group.previous.0.fabricPodPGrp.children.4.fabricRsTimePol.attributes.tnDatetimePolName == ''
+ - nm_remove_group.previous.0.fabricPodPGrp.children.5.fabricRsPodPGrpBGPRRP.attributes.tnBgpInstPolName == ''
+ - nm_remove_group.previous.0.fabricPodPGrp.children.6.fabricRsPodPGrpIsisDomP.attributes.tnIsisDomPolName == ''
+ - cm_remove_group_again is not changed
+ - nm_remove_group_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_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_fabric_spine_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml
new file mode 100644
index 000000000..684a9a874
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_profile/tasks/main.yml
@@ -0,0 +1,122 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_spine_switch_prf if it already exists
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
+
+# CREATE SPINE SWITCH POLICY
+- name: Create ansible_spine_switch_prf
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: present
+ register: add_switch_prf
+
+- name: Verify profile creation
+ assert:
+ that:
+ - add_switch_prf.current.0.fabricSpineP.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf"
+ - add_switch_prf.current.0.fabricSpineP.attributes.name == "ansible_spine_switch_prf"
+ - add_switch_prf.current.0.fabricSpineP.attributes.annotation == 'orchestrator:ansible'
+
+# CREATE SPINE SWITCH POLICY AGAIN TO TEST IDEMPOTENCE
+- name: Create ansible_spine_switch_prf again
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: present
+ register: add_switch_prf_again
+
+- name: Verify profile creation idempotence
+ assert:
+ that:
+ - add_switch_prf_again is not changed
+ - add_switch_prf_again.current.0.fabricSpineP.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf"
+ - add_switch_prf_again.current.0.fabricSpineP.attributes.name == "ansible_spine_switch_prf"
+
+# QUERY SPINE SWITCH POLICY
+- name: query spine switch profile
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: query
+ register: query_switch_prf
+
+- name: Verify profile query
+ assert:
+ that:
+ - query_switch_prf is not changed
+ - query_switch_prf.current.0.fabricSpineP.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf"
+ - query_switch_prf.current.0.fabricSpineP.attributes.name == "ansible_spine_switch_prf"
+
+# QUERY ALL SPINE SWITCH POLICIES
+- name: query all spine switch profiles
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ state: query
+ register: query_switch_prf_all
+
+- name: Verify profile query idempotence
+ assert:
+ that:
+ - query_switch_prf_all is not changed
+
+# DELETE SPINE SWITCH PROFILE
+- name: Delete ansible_spine_switch_prf
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
+ register: delete_switch_prf
+
+- name: Verify profile deletion
+ assert:
+ that:
+ - delete_switch_prf is changed
+ - delete_switch_prf.current == []
+ - delete_switch_prf.previous.0.fabricSpineP.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf"
+ - delete_switch_prf.previous.0.fabricSpineP.attributes.name == "ansible_spine_switch_prf"
+
+# DELETE SPINE SWITCH PROFILE AGAIN TO TEST IDEMPOTENCE
+- name: Delete ansible_spine_switch_prf again
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
+ register: delete_switch_prf_again
+
+- name: Verify profile deletion idempotence
+ assert:
+ that:
+ - delete_switch_prf_again is not changed
+ - delete_switch_prf_again.current == []
+
+# CLEAN UP ENVIRONMENT
+- name: Remove ansible_spine_switch_prf
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/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_spine_switch_assoc/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml
new file mode 100644
index 000000000..697590fae
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_spine_switch_assoc/tasks/main.yml
@@ -0,0 +1,194 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_spine_switch_prf if it already exists
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
+
+# CREATE SPINE SWITCH POLICY
+- name: Create ansible_spine_switch_prf
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: present
+
+# CREATE SPINE SWITCH ASSOCIATION
+- name: Create a spine switch profile association
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc
+ policy_group: ansible_spine_pol_grp1
+ state: present
+ register: add_association
+
+- name: Verify association creation
+ assert:
+ that:
+ - add_association.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range"
+ - add_association.current.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc"
+ - add_association.current.0.fabricSpineS.attributes.type == "range"
+ - add_association.current.0.fabricSpineS.attributes.annotation == 'orchestrator:ansible'
+
+- name: Verify Policy Group association
+ assert:
+ that:
+ - add_association.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp1"
+
+# CREATE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE
+- name: Create a spine switch profile association again
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc
+ policy_group: ansible_spine_pol_grp1
+ state: present
+ register: add_association_again
+
+- name: Verify association creation idempotence
+ assert:
+ that:
+ - add_association_again is not changed
+ - add_association_again.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range"
+ - add_association_again.current.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc"
+ - add_association_again.current.0.fabricSpineS.attributes.type == "range"
+
+- name: Verify Policy Group association idempotence
+ assert:
+ that:
+ - add_association_again.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp1"
+
+# CREATE SPINE SWITCH ASSOCIATION WITHOUT POLICY GROUP
+- name: Create a spine switch profile association without a policy group
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc2
+ state: present
+ register: add_association_without_policy_group
+
+- name: Verify association creation
+ assert:
+ that:
+ - add_association_without_policy_group.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc2-typ-range"
+ - add_association_without_policy_group.current.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc2"
+ - add_association_without_policy_group.current.0.fabricSpineS.attributes.type == "range"
+
+# UPDATE SPINE SWITCH POLICY GROUP ASSOCIATION
+- name: Update a spine switch profile association
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc
+ policy_group: ansible_spine_pol_grp2
+ state: present
+ register: update_association
+
+- name: Verify association update
+ assert:
+ that:
+ - update_association is changed
+ - update_association.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range"
+ - update_association.current.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc"
+ - update_association.current.0.fabricSpineS.attributes.type == "range"
+
+- name: Verify Policy Group association update
+ assert:
+ that:
+ - update_association.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp2"
+
+# QUERY SPINE SWITCH ASSOCIATION
+- name: Query spine switch profile association
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc
+ state: query
+ register: query_association
+
+- name: Verify query data
+ assert:
+ that:
+ - query_association is not changed
+ - query_association.current.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range"
+ - query_association.current.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc"
+ - query_association.current.0.fabricSpineS.attributes.type == "range"
+
+- name: Verify Policy Group association
+ assert:
+ that:
+ - query_association.current.0.fabricSpineS.children.0.fabricRsSpNodePGrp.attributes.tDn == "uni/fabric/funcprof/spnodepgrp-ansible_spine_pol_grp2"
+
+# QUERY ALL SPINE SWITCH ASSOCIATIONS
+- name: Query spine switch profile association
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ state: query
+ register: query_association_all
+
+- name: Verify query all idempotence
+ assert:
+ that:
+ - query_association_all is not changed
+
+# DELETE SPINE SWITCH ASSOCIATION
+- name: Delete spine switch profile association
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc
+ state: absent
+ register: delete_association
+
+- name: Verify association removal
+ assert:
+ that:
+ - delete_association is changed
+ - delete_association.current == []
+ - delete_association.previous.0.fabricSpineS.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range"
+ - delete_association.previous.0.fabricSpineS.attributes.name == "ansible_spine_switch_assoc"
+ - delete_association.previous.0.fabricSpineS.attributes.type == "range"
+
+# DELETE SPINE SWITCH ASSOCIATION AGAIN TO TEST IDEMPOTENCE
+- name: Delete spine switch profile association again
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc
+ state: absent
+ register: delete_association_again
+
+- name: Verify association removal idempotence
+ assert:
+ that:
+ - delete_association_again is not changed
+ - delete_association_again.current == []
+
+# CLEAN UP ENVIRONMENT
+- name: Remove ansible_spine_switch_prf
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/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_switch_block/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/tasks/main.yml
new file mode 100644
index 000000000..5bd4ce68b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_block/tasks/main.yml
@@ -0,0 +1,268 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_spine_switch_prf if it already exists
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
+
+- name: Remove ansible_leaf_switch_prf if it already exists
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
+
+# TODO: Add testing for Fabric Leaf Blocks
+
+# CREATE SPINE SWITCH POLICY
+- name: Create ansible_spine_switch_prf
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: present
+
+# CREATE LEAF SWITCH POLICY
+- name: Create ansible_leaf_switch_prf
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: present
+
+# CREATE SPINE SWITCH ASSOCIATION
+- name: Create a spine switch profile association
+ aci_fabric_spine_switch_assoc:
+ <<: *aci_info
+ profile: ansible_spine_switch_prf
+ name: ansible_spine_switch_assoc
+ policy_group: ansible_spine_pol_grp1
+ state: present
+
+# CREATE LEAF SWITCH ASSOCIATION
+- name: Create a leaf switch profile association
+ aci_fabric_leaf_switch_assoc:
+ <<: *aci_info
+ profile: ansible_leaf_switch_prf
+ name: ansible_leaf_switch_assoc
+ policy_group: ansible_leaf_pol_grp1
+ state: present
+
+# CREATE SPINE SWITCH BLOCK
+- name: Create a spine switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: spine
+ profile: ansible_spine_switch_prf
+ association: ansible_spine_switch_assoc
+ name: ansible_spine_block
+ from_: 103
+ to_: 103
+ state: present
+ register: add_switch_block
+
+- name: Verify spine block creation
+ assert:
+ that:
+ - add_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range/nodeblk-ansible_spine_block"
+ - add_switch_block.current.0.fabricNodeBlk.attributes.name == "ansible_spine_block"
+ - add_switch_block.current.0.fabricNodeBlk.attributes.annotation == 'orchestrator:ansible'
+
+# ADD SPINE SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE
+- name: Create a spine switch association block again
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: spine
+ profile: ansible_spine_switch_prf
+ association: ansible_spine_switch_assoc
+ name: ansible_spine_block
+ from_: 103
+ to_: 103
+ state: present
+ register: add_switch_block_again
+
+- name: Verify spine block creation idempotence
+ assert:
+ that:
+ - add_switch_block_again is not changed
+ - add_switch_block_again.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range/nodeblk-ansible_spine_block"
+ - add_switch_block_again.current.0.fabricNodeBlk.attributes.name == "ansible_spine_block"
+
+# CREATE LEAF SWITCH BLOCK
+- name: Create a leaf switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: leaf
+ profile: ansible_leaf_switch_prf
+ association: ansible_leaf_switch_assoc
+ name: ansible_leaf_block
+ from_: 103
+ to_: 103
+ state: present
+ register: add_leaf_switch_block
+
+- name: Verify leaf block creation
+ assert:
+ that:
+ - add_leaf_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range/nodeblk-ansible_leaf_block"
+ - add_leaf_switch_block.current.0.fabricNodeBlk.attributes.name == "ansible_leaf_block"
+
+# ADD LEAF SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE
+- name: Create a leaf switch association block again
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: leaf
+ profile: ansible_leaf_switch_prf
+ association: ansible_leaf_switch_assoc
+ name: ansible_leaf_block
+ from_: 103
+ to_: 103
+ state: present
+ register: add_leaf_switch_block_again
+
+- name: Verify leaf block creation idempotence
+ assert:
+ that:
+ - add_leaf_switch_block_again is not changed
+ - add_leaf_switch_block_again.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range/nodeblk-ansible_leaf_block"
+ - add_leaf_switch_block_again.current.0.fabricNodeBlk.attributes.name == "ansible_leaf_block"
+
+# QUERY SPINE SWITCH BLOCK
+- name: Query spine switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: spine
+ profile: ansible_spine_switch_prf
+ association: ansible_spine_switch_assoc
+ name: ansible_spine_block
+ state: query
+ register: query_switch_block
+
+- name: Verify block query
+ assert:
+ that:
+ - query_switch_block is not changed
+ - query_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range/nodeblk-ansible_spine_block"
+ - query_switch_block.current.0.fabricNodeBlk.attributes.name == "ansible_spine_block"
+
+# QUERY LEAF SWITCH BLOCK
+- name: Query leaf switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: leaf
+ profile: ansible_leaf_switch_prf
+ association: ansible_leaf_switch_assoc
+ name: ansible_leaf_block
+ state: query
+ register: query_leaf_switch_block
+
+- name: Verify leaf block query
+ assert:
+ that:
+ - query_leaf_switch_block is not changed
+ - query_leaf_switch_block.current.0.fabricNodeBlk.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range/nodeblk-ansible_leaf_block"
+ - query_leaf_switch_block.current.0.fabricNodeBlk.attributes.name == "ansible_leaf_block"
+
+# REMOVE SPINE SWITCH BLOCK
+- name: Remove spine switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: spine
+ profile: ansible_spine_switch_prf
+ association: ansible_spine_switch_assoc
+ name: ansible_spine_block
+ state: absent
+ register: delete_switch_block
+
+- name: Verify spine switch block removal
+ assert:
+ that:
+ - delete_switch_block is changed
+ - delete_switch_block.current == []
+ - delete_switch_block.previous.0.fabricNodeBlk.attributes.dn == "uni/fabric/spprof-ansible_spine_switch_prf/spines-ansible_spine_switch_assoc-typ-range/nodeblk-ansible_spine_block"
+ - delete_switch_block.previous.0.fabricNodeBlk.attributes.name == "ansible_spine_block"
+
+# REMOVE SPINE SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE
+- name: Remove spine switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: spine
+ profile: ansible_spine_switch_prf
+ association: ansible_spine_switch_assoc
+ name: ansible_spine_block
+ state: absent
+ register: delete_switch_block
+
+- name: Verify spine switch block removal idempotence
+ assert:
+ that:
+ - delete_switch_block is not changed
+ - delete_switch_block.current == []
+
+# REMOVE LEAF SWITCH BLOCK
+- name: Remove leaf switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: leaf
+ profile: ansible_leaf_switch_prf
+ association: ansible_leaf_switch_assoc
+ name: ansible_leaf_block
+ state: absent
+ register: delete_leaf_switch_block
+
+- name: Verify leaf switch block removal
+ assert:
+ that:
+ - delete_leaf_switch_block is changed
+ - delete_leaf_switch_block.current == []
+ - delete_leaf_switch_block.previous.0.fabricNodeBlk.attributes.dn == "uni/fabric/leprof-ansible_leaf_switch_prf/leaves-ansible_leaf_switch_assoc-typ-range/nodeblk-ansible_leaf_block"
+ - delete_leaf_switch_block.previous.0.fabricNodeBlk.attributes.name == "ansible_leaf_block"
+
+# REMOVE LEAF SWITCH BLOCK AGAIN TO TEST IDEMPOTENCE
+- name: Remove leaf switch association block
+ aci_fabric_switch_block:
+ <<: *aci_info
+ switch_type: leaf
+ profile: ansible_leaf_switch_prf
+ association: ansible_leaf_switch_assoc
+ name: ansible_leaf_block
+ state: absent
+ register: delete_leaf_switch_block
+
+- name: Verify leaf switch block removal idempotence
+ assert:
+ that:
+ - delete_leaf_switch_block is not changed
+ - delete_leaf_switch_block.current == []
+
+# CLEAN UP ENVIRONMENT
+- name: Remove ansible_spine_switch_prf
+ aci_fabric_spine_profile:
+ <<: *aci_info
+ name: ansible_spine_switch_prf
+ state: absent
+
+- name: Remove ansible_leaf_switch_prf
+ aci_fabric_leaf_profile:
+ <<: *aci_info
+ name: ansible_leaf_switch_prf
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_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_switch_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml
new file mode 100644
index 000000000..83f5355a6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_switch_policy_group/tasks/main.yml
@@ -0,0 +1,344 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_fabric_leaf_policy_group if it already exists
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_leaf_policy_group
+ switch_type: leaf
+ state: absent
+
+- name: Remove ansible_fabric_spine_policy_group if it already exists
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_spine_policy_group
+ switch_type: spine
+ state: absent
+
+# ADD Fabric Leaf Policy Group
+- name: Add ansible_fabric_leaf_policy_group
+ cisco.aci.aci_fabric_switch_policy_group: &aci_fabric_leaf_policy_group_present
+ <<: *aci_info
+ name: ansible_fabric_leaf_policy_group
+ switch_type: leaf
+ monitoring_policy: default
+ tech_support_export_policy: default
+ core_export_policy: default
+ inventory_policy: default
+ power_redundancy_policy: default
+ analytics_cluster: ansible_test
+ analytics_name: ansible_test
+ state: present
+ register: add_fabric_leaf_policy_group
+
+- name: Verify that ansible_fabric_leaf_policy_group has been created with correct attributes
+ assert:
+ that:
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group"
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group"
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.annotation == 'orchestrator:ansible'
+
+- name: Verify that ansible_fabric_leaf_policy_group children have correct attributes
+ assert:
+ that:
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test"
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.2.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == ""
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.3.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.4.fabricRsTwampServerPol.attributes.tnTwampServerPolName == ""
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.5.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == ""
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.6.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.7.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - add_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.8.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+# ADD Fabric Leaf Policy Group again to check idempotency
+- name: Add ansible_fabric_leaf_policy_group again to test idempotence
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_fabric_leaf_policy_group_present
+ register: add_fabric_leaf_policy_group_again
+
+- name: Verify that ansible_fabric_leaf_policy_group has not been changed
+ assert:
+ that:
+ - add_fabric_leaf_policy_group_again is not changed
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group"
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group"
+
+- name: Verify that ansible_fabric_leaf_policy_group children are still correct
+ assert:
+ that:
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test"
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.2.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == ""
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.3.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.4.fabricRsTwampServerPol.attributes.tnTwampServerPolName == ""
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.5.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == ""
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.6.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.7.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - add_fabric_leaf_policy_group_again.current.0.fabricLeNodePGrp.children.8.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+# ADD Fabric Spine Policy Group
+- name: Add ansible_fabric_spine_policy_group
+ cisco.aci.aci_fabric_switch_policy_group: &aci_fabric_spine_policy_group_present
+ <<: *aci_info
+ name: ansible_fabric_spine_policy_group
+ switch_type: spine
+ monitoring_policy: default
+ tech_support_export_policy: default
+ core_export_policy: default
+ inventory_policy: default
+ power_redundancy_policy: default
+ state: present
+ register: add_fabric_spine_policy_group
+
+- name: Verify that ansible_fabric_spine_policy_group has been created with correct attributes
+ assert:
+ that:
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group"
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group"
+
+- name: Verify that ansible_fabric_spine_policy_group children have correct attributes
+ assert:
+ that:
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == ""
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.2.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.3.fabricRsTwampServerPol.attributes.tnTwampServerPolName == ""
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.4.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == ""
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.5.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.6.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - add_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.7.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+# ADD Fabric Spine Policy Group again to check idempotency
+- name: Add ansible_fabric_spine_policy_group again to test idempotence
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_fabric_spine_policy_group_present
+ register: add_fabric_spine_policy_group_again
+
+- name: Verify that ansible_fabric_spine_policy_group has not been changed
+ assert:
+ that:
+ - add_fabric_spine_policy_group_again is not changed
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group"
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group"
+
+- name: Verify that ansible_fabric_spine_policy_group children are still correct
+ assert:
+ that:
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == ""
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.2.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.3.fabricRsTwampServerPol.attributes.tnTwampServerPolName == ""
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.4.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == ""
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.5.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.6.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - add_fabric_spine_policy_group_again.current.0.fabricSpNodePGrp.children.7.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+# MODIFY Fabric Leaf Policy Group
+- name: Update ansible_fabric_leaf_policy_group
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_leaf_policy_group
+ switch_type: leaf
+ twamp_server_policy: default
+ twamp_responder_policy: default
+ node_control_policy: default
+ register: update_fabric_leaf_policy_group
+
+- name: Verify ansible_fabric_leaf_policy_group is changed
+ assert:
+ that:
+ - update_fabric_leaf_policy_group is changed
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group"
+
+- name: Verify ansible_fabric_leaf_policy_group children are updated
+ assert:
+ that:
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.2.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.3.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.4.fabricRsTwampServerPol.attributes.tnTwampServerPolName == "default"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.5.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == "default"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.6.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.7.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - update_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.8.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+# MODIFY Fabric Spine Policy Group
+- name: Update ansible_fabric_spine_policy_group
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_spine_policy_group
+ switch_type: spine
+ twamp_server_policy: default
+ twamp_responder_policy: default
+ node_control_policy: default
+ register: update_fabric_spine_policy_group
+
+- name: Verify ansible_fabric_spine_policy_group is changed
+ assert:
+ that:
+ - update_fabric_spine_policy_group is changed
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group"
+
+- name: Verify ansible_fabric_spine_policy_group children are updated
+ assert:
+ that:
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.2.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.3.fabricRsTwampServerPol.attributes.tnTwampServerPolName == "default"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.4.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == "default"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.5.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.6.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - update_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.7.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+# QUERY Fabric Leaf Policy Group
+- name: Query ansible_fabric_leaf_policy_group
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_leaf_policy_group
+ switch_type: leaf
+ state: query
+ register: query_fabric_leaf_policy_group
+
+- name: Verify attributes
+ assert:
+ that:
+ - query_fabric_leaf_policy_group is not changed
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.dn == "uni/fabric/funcprof/lenodepgrp-ansible_fabric_leaf_policy_group"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.attributes.name == "ansible_fabric_leaf_policy_group"
+
+- name: Verify children
+ assert:
+ that:
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.2.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.3.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.4.fabricRsTwampServerPol.attributes.tnTwampServerPolName == "default"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.5.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == "default"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.6.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.7.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - query_fabric_leaf_policy_group.current.0.fabricLeNodePGrp.children.8.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+- name: Query all Fabric Leaf Policy Groups
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ switch_type: leaf
+ state: query
+ register: query_fabric_leaf_policy_group_all
+
+- name: Verify query all is idempotent
+ assert:
+ that:
+ - query_fabric_leaf_policy_group_all is not changed
+
+# QUERY Fabric Spine Policy Group
+- name: Query ansible_fabric_spine_policy_group
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_spine_policy_group
+ switch_type: spine
+ state: query
+ register: query_fabric_spine_policy_group
+
+- name: Verify attributes
+ assert:
+ that:
+ - query_fabric_spine_policy_group is not changed
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.dn == "uni/fabric/funcprof/spnodepgrp-ansible_fabric_spine_policy_group"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.attributes.name == "ansible_fabric_spine_policy_group"
+
+- name: Verify children
+ assert:
+ that:
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.2.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.3.fabricRsTwampServerPol.attributes.tnTwampServerPolName == "default"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.4.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == "default"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.5.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.6.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - query_fabric_spine_policy_group.current.0.fabricSpNodePGrp.children.7.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+- name: Query all Fabric Spine Policy Groups
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ switch_type: spine
+ state: query
+ register: query_fabric_spine_policy_group_all
+
+- name: Verify query all is idempotent
+ assert:
+ that:
+ - query_fabric_spine_policy_group_all is not changed
+
+# DELETE Fabric Leaf Policy Group
+- name: Remove ansible_fabric_leaf_policy_group
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_leaf_policy_group
+ switch_type: leaf
+ state: absent
+ register: delete_fabric_leaf_policy_group
+
+- name: Verify Fabric Leaf Policy Group deletion
+ assert:
+ that:
+ - delete_fabric_leaf_policy_group is changed
+ - delete_fabric_leaf_policy_group.current == []
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.0.fabricRsNodeCfgSrv.attributes.tDn == "uni/fabric/analytics/cluster-ansible_test/cfgsrv-ansible_test"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.1.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.2.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.3.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.4.fabricRsTwampServerPol.attributes.tnTwampServerPolName == "default"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.5.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == "default"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.6.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.7.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - delete_fabric_leaf_policy_group.previous.0.fabricLeNodePGrp.children.8.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
+
+# DELETE Fabric Spine Policy Group
+- name: Remove ansible_fabric_spine_policy_group
+ cisco.aci.aci_fabric_switch_policy_group:
+ <<: *aci_info
+ name: ansible_fabric_spine_policy_group
+ switch_type: spine
+ state: absent
+ register: delete_fabric_spine_policy_group
+
+- name: Verify Fabric Spine Policy Group deletion
+ assert:
+ that:
+ - delete_fabric_spine_policy_group is changed
+ - delete_fabric_spine_policy_group.current == []
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.0.fabricRsCallhomeInvPol.attributes.tnCallhomeInvPName == "default"
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.1.fabricRsTwampResponderPol.attributes.tnTwampResponderPolName == "default"
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.2.fabricRsPsuInstPol.attributes.tnPsuInstPolName == "default"
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.3.fabricRsTwampServerPol.attributes.tnTwampServerPolName == "default"
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.4.fabricRsNodeCtrl.attributes.tnFabricNodeControlName == "default"
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.5.fabricRsMonInstFabricPol.attributes.tnMonFabricPolName == "default"
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.6.fabricRsNodeCoreP.attributes.tnDbgexpCorePName == "default"
+ - delete_fabric_spine_policy_group.previous.0.fabricSpNodePGrp.children.7.fabricRsNodeTechSupP.attributes.tnDbgexpTechSupPName == "default"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml
new file mode 100644
index 000000000..a8928de57
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml
@@ -0,0 +1,224 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.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
+
+# CLEAN ENVIRONMENT
+- name: Add 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") }}'
+ tenant: ansible_test
+ state: present
+
+- name: Remove filter
+ cisco.aci.aci_filter: &filter_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
+ filter: filter_test
+ state: absent
+
+# ADD FILTER
+- name: Add filter (check_mode)
+ cisco.aci.aci_filter: &filter_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
+ filter: filter_test
+ state: present
+ check_mode: true
+ register: cm_add_filter
+
+- name: Add filter again (check_mode)
+ cisco.aci.aci_filter: *filter_present
+ check_mode: true
+ register: cm_add_filter_again
+
+- name: Add filter (normal mode)
+ cisco.aci.aci_filter: *filter_present
+ register: nm_add_filter
+
+- name: Add filter again (normal mode)
+ cisco.aci.aci_filter: *filter_present
+ register: nm_add_filter_again
+
+- name: Verify add_filter
+ assert:
+ that:
+ - cm_add_filter is changed
+ - cm_add_filter_again is changed
+ - nm_add_filter is changed
+ - nm_add_filter.current.0.vzFilter.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_filter_again is not changed
+
+# CHANGE FILTER
+- name: Change description of filter (check_mode)
+ cisco.aci.aci_filter:
+ <<: *filter_present
+ description: Ansible test filter
+ check_mode: true
+ register: cm_add_filter_descr
+
+- name: Change description of filter again (check_mode)
+ cisco.aci.aci_filter:
+ <<: *filter_present
+ description: Ansible test filter
+ check_mode: true
+ register: cm_add_filter_descr_again
+
+- name: Change description of filter (normal mode)
+ cisco.aci.aci_filter:
+ <<: *filter_present
+ description: Ansible test filter
+ register: nm_add_filter_descr
+
+- name: Change description of filter again (normal mode)
+ cisco.aci.aci_filter:
+ <<: *filter_present
+ description: Ansible test filter
+ register: nm_add_filter_descr_again
+
+- name: Verify add_filter_descr
+ assert:
+ that:
+ - cm_add_filter_descr is changed
+ - cm_add_filter_descr_again is changed
+ - nm_add_filter_descr is changed
+ - nm_add_filter_descr_again is not changed
+
+# ADD FILTER AGAIN
+- name: Add filter again with no description (check_mode)
+ cisco.aci.aci_filter: *filter_present
+ check_mode: true
+ register: cm_add_filter_again_no_descr
+
+- name: Add filter again with no description (normal mode)
+ cisco.aci.aci_filter: *filter_present
+ register: nm_add_filter_again_no_descr
+
+- name: Verify add_filter_again_no_descr
+ assert:
+ that:
+ - cm_add_filter_again_no_descr is not changed
+ - nm_add_filter_again_no_descr is not changed
+
+# QUERY ALL FILTERS
+- name: Query all filters (check_mode)
+ cisco.aci.aci_filter: &filter_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_filters
+
+- name: Query all filters (normal mode)
+ cisco.aci.aci_filter: *filter_query
+ register: nm_query_all_filters
+
+- name: Verify query_all_filters
+ assert:
+ that:
+ - cm_query_all_filters is not changed
+ - nm_query_all_filters is not changed
+ # NOTE: Order of filters is not stable between calls
+ #- cm_query_all_filters == nm_query_all_filters
+
+# QUERY A FILTER
+- name: Query our filter
+ cisco.aci.aci_filter:
+ <<: *filter_query
+ tenant: ansible_test
+ filter: filter_test
+ check_mode: true
+ register: cm_query_filter
+
+- name: Query our filter
+ cisco.aci.aci_filter:
+ <<: *filter_query
+ tenant: ansible_test
+ filter: filter_test
+ register: nm_query_filter
+
+- name: Verify query_filter
+ assert:
+ that:
+ - cm_query_filter is not changed
+ - nm_query_filter is not changed
+ - cm_query_filter == nm_query_filter
+
+# REMOVE FILTER
+- name: Remove filter (check_mode)
+ cisco.aci.aci_filter: *filter_absent
+ check_mode: true
+ register: cm_remove_filter
+
+- name: Remove filter again (check_mode)
+ cisco.aci.aci_filter: *filter_absent
+ check_mode: true
+ register: cm_remove_filter_again
+
+- name: Remove filter (normal mode)
+ cisco.aci.aci_filter: *filter_absent
+ register: nm_remove_filter
+
+- name: Remove filter again (normal mode)
+ cisco.aci.aci_filter: *filter_absent
+ register: nm_remove_filter_again
+
+- name: Verify remove_filter
+ assert:
+ that:
+ - cm_remove_filter is changed
+ - cm_remove_filter_again is changed
+ - nm_remove_filter is changed
+ - nm_remove_filter_again is not changed
+
+# QUERY NON-EXISTING FILTER
+# FIXME: Should this fail or return empty values ?
+- name: Query non-existing filter (check_mode)
+ cisco.aci.aci_filter:
+ <<: *filter_query
+ tenant: ansible_test
+ filter: filter_test
+ check_mode: true
+ register: cm_query_non_filter
+
+- name: Query non-existing filter (normal mode)
+ cisco.aci.aci_filter:
+ <<: *filter_query
+ tenant: ansible_test
+ filter: filter_test
+ register: nm_query_non_filter
+
+- name: Verify query_non_filter
+ assert:
+ that:
+ - cm_query_non_filter is not changed
+ - nm_query_non_filter is not changed
+ - cm_query_non_filter == nm_query_non_filter
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..77093a670
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml
@@ -0,0 +1,315 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("debug") }}'
+
+- name: 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
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/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_source/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml
new file mode 100644
index 000000000..d9287506c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml
@@ -0,0 +1,208 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# CLEAN ENVIRONMENT
+- name: Remove firmware source
+ cisco.aci.aci_firmware_source: &source_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") }}'
+ source: '{{ item }}'
+ state: absent
+ loop:
+ - ansible_test_1
+ - ansible_test_2
+
+# ADD SOURCE
+- name: Add source (check_mode)
+ aci_firmware_source: &source_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") }}'
+ source: ansible_test_1
+ url: foobar.cisco.com/download/cisco/aci/aci-msft-pkg-3.1.1i.zip
+ url_protocol: http
+ state: present
+ check_mode: true
+ register: cm_add_source
+
+- name: Add source (normal mode)
+ aci_firmware_source:
+ <<: *source_present
+ register: nm_add_source
+
+- name: Verify add_source
+ assert:
+ that:
+ - cm_add_source is changed
+ - nm_add_source is changed
+ - cm_add_source.sent.firmwareOSource.attributes.name == nm_add_source.sent.firmwareOSource.attributes.name == 'ansible_test_1'
+ - cm_add_source.sent.firmwareOSource.attributes.proto == nm_add_source.sent.firmwareOSource.attributes.proto == 'http'
+ - cm_add_source.sent.firmwareOSource.attributes.url == nm_add_source.sent.firmwareOSource.attributes.url == 'foobar.cisco.com/download/cisco/aci/aci-msft-pkg-3.1.1i.zip'
+ - cm_add_source.proposed.firmwareOSource.attributes.name == nm_add_source.proposed.firmwareOSource.attributes.name == 'ansible_test_1'
+ - cm_add_source.proposed.firmwareOSource.attributes.proto == nm_add_source.proposed.firmwareOSource.attributes.proto == 'http'
+ - cm_add_source.proposed.firmwareOSource.attributes.url == nm_add_source.proposed.firmwareOSource.attributes.url == 'foobar.cisco.com/download/cisco/aci/aci-msft-pkg-3.1.1i.zip'
+ - cm_add_source.current == cm_add_source.previous == nm_add_source.previous == []
+ - nm_add_source.current.0.firmwareOSource.attributes.name == 'ansible_test_1'
+ - nm_add_source.current.0.firmwareOSource.attributes.proto == 'http'
+ - nm_add_source.current.0.firmwareOSource.attributes.url == 'foobar.cisco.com/download/cisco/aci/aci-msft-pkg-3.1.1i.zip'
+ - nm_add_source.current.0.firmwareOSource.attributes.annotation == 'orchestrator:ansible'
+
+- name: Add source again (check_mode)
+ aci_firmware_source: *source_present
+ check_mode: true
+ register: cm_add_source_again
+
+- name: Add source again (normal mode)
+ aci_firmware_source:
+ <<: *source_present
+ register: nm_add_source_again
+
+- name: Verify add_source_again
+ assert:
+ that:
+ - cm_add_source_again is not changed
+
+- name: Add another source (normal mode)
+ aci_firmware_source:
+ <<: *source_present
+ source: ansible_test_2
+ register: nm_add_source
+
+# QUERY ALL SOURCES
+- name: Query all sources (check_mode)
+ cisco.aci.aci_firmware_source: &source_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_sources
+
+- name: Query all sources (normal mode)
+ cisco.aci.aci_firmware_source: *source_query
+ register: nm_query_all_sources
+
+- name: Verify query_all_sources
+ assert:
+ that:
+ - cm_query_all_sources is not changed
+ - nm_query_all_sources is not changed
+ - cm_query_all_sources == nm_query_all_sources
+ - nm_query_all_sources.current.0.firmwareRepoP.children | length >= 2
+
+# QUERY A SOURCE
+- name: Query our source (check_mode)
+ aci_firmware_source:
+ <<: *source_query
+ source: ansible_test_1
+ check_mode: true
+ register: cm_query_source
+
+- name: Query our source (normal mode)
+ aci_firmware_source:
+ <<: *source_query
+ source: ansible_test_1
+ register: nm_query_source
+
+- name: Verify query_source
+ assert:
+ that:
+ - cm_query_source is not changed
+ - nm_query_source is not changed
+ - cm_query_source == nm_query_source
+ - nm_query_source.current.0.firmwareOSource.attributes.dn == 'uni/fabric/fwrepop/osrc-ansible_test_1'
+ - nm_query_source.current.0.firmwareOSource.attributes.name == 'ansible_test_1'
+
+# REMOVE SOURCE
+- name: Remove source (check_mode)
+ aci_firmware_source: &source_remove
+ <<: *source_query
+ source: ansible_test_1
+ state: absent
+ check_mode: true
+ register: cm_remove_source
+
+- name: Remove source (normal mode)
+ aci_firmware_source: *source_remove
+ register: nm_remove_source
+
+- name: Verify remove_source
+ assert:
+ that:
+ - cm_remove_source is changed
+ - nm_remove_source is changed
+ - cm_remove_source.current.0.firmwareOSource.attributes.dn == cm_remove_source.previous.0.firmwareOSource.attributes.dn == nm_remove_source.previous.0.firmwareOSource.attributes.dn == 'uni/fabric/fwrepop/osrc-ansible_test_1'
+ - nm_remove_source.current == []
+
+- name: Remove source again (check_mode)
+ aci_firmware_source: *source_remove
+ check_mode: true
+ register: cm_remove_source_again
+
+- name: Remove source again (normal mode)
+ aci_firmware_source: *source_remove
+ register: nm_remove_source_again
+
+- name: Verify remove_source_again
+ assert:
+ that:
+ - cm_remove_source_again is not changed
+ - nm_remove_source_again is not changed
+
+# QUERY NON-EXISTING SOURCE
+- name: Query non-existing source (check_mode)
+ aci_firmware_source:
+ <<: *source_query
+ source: non_existing_source
+ check_mode: true
+ register: cm_query_non_source
+
+- name: Query non-existing source (normal mode)
+ aci_firmware_source:
+ <<: *source_query
+ source: non_existing_source
+ register: nm_query_non_source
+
+- name: Verify query_non_source
+ assert:
+ that:
+ - cm_query_non_source is not changed
+ - nm_query_non_source is not changed
+ - cm_query_non_source == nm_query_non_source
+ - nm_query_non_source.current == []
+
+# PROVOKE ERRORS
+- name: Error when required parameter is missing
+ cisco.aci.aci_firmware_source:
+ 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") }}'
+ state: present
+ ignore_errors: true
+ register: error_on_missing_required_param
+
+- name: Verify error_on_missing_required_param
+ assert:
+ that:
+ - error_on_missing_required_param is failed
+ - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: source, url"'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_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_igmp_interface_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml
new file mode 100644
index 000000000..eac9daf6b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_igmp_interface_policy/tasks/main.yml
@@ -0,0 +1,239 @@
+# 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 }}"
+ port: "{{ aci_port | default(omit) }}"
+ 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_tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ name: ansible_tenant
+ state: absent
+
+# CREATE IGMP INTERFACE POLICY
+- name: Create the ansible_tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ name: ansible_tenant
+ state: present
+
+- name: Create an IGMP interface policy (check mode)
+ cisco.aci.aci_igmp_interface_policy: &aci_igmp
+ <<: *aci_info
+ name: ansible_igmp_intf_policy
+ tenant: ansible_tenant
+ description: Test IGMP Interface Policy
+ group_timeout: 300
+ query_interval: 100
+ query_response_interval: 8
+ last_member_count: 3
+ last_member_response: 5
+ startup_query_count: 3
+ startup_query_interval: 5
+ querier_timeout: 200
+ robustness_variable: 3
+ igmp_version: v3
+ allow_v3_asm: true
+ fast_leave: true
+ report_link_local_groups: false
+ check_mode: yes
+ register: cm_create_igmp_intf_policy
+
+- name: Create an IGMP interface policy
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_igmp
+ register: nm_create_igmp_intf_policy
+
+- name: Create IGMP interface policy again to test idempotence
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_igmp
+ register: nm_create_igmp_intf_policy_again
+
+- name: Create IGMP interface policy with default parameters
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_info
+ name: ansible_igmp_dflt_intf_policy
+ tenant: ansible_tenant
+ register: default_igmp_intf_policy
+
+- name: Verify creation of IGMP interface policy
+ ansible.builtin.assert:
+ that:
+ - cm_create_igmp_intf_policy is changed
+ - nm_create_igmp_intf_policy is changed
+ - nm_create_igmp_intf_policy_again is not changed
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.dn == "uni/tn-ansible_tenant/igmpIfPol-ansible_igmp_intf_policy"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.descr == "Test IGMP Interface Policy"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.name == "ansible_igmp_intf_policy"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.grpTimeout == "300"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.queryIntvl == "100"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.rspIntvl == "8"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.lastMbrCnt == "3"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.lastMbrRespTime == "5"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.startQueryCnt == "3"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.startQueryIntvl == "5"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.querierTimeout == "200"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.robustFac == "3"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.ver == "v3"
+ - nm_create_igmp_intf_policy.current.0.igmpIfPol.attributes.ifCtrl == "allow-v3-asm,fast-leave"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.dn == "uni/tn-ansible_tenant/igmpIfPol-ansible_igmp_intf_policy"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.descr == "Test IGMP Interface Policy"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.name == "ansible_igmp_intf_policy"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.grpTimeout == "300"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.queryIntvl == "100"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.rspIntvl == "8"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.lastMbrCnt == "3"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.lastMbrRespTime == "5"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.startQueryCnt == "3"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.startQueryIntvl == "5"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.querierTimeout == "200"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.robustFac == "3"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.ver == "v3"
+ - nm_create_igmp_intf_policy_again.current.0.igmpIfPol.attributes.ifCtrl == "allow-v3-asm,fast-leave"
+
+- name: Verify default values
+ ansible.builtin.assert:
+ that:
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.grpTimeout == "260"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.queryIntvl == "125"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.rspIntvl == "10"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.lastMbrCnt == "2"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.lastMbrRespTime == "1"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.startQueryCnt == "2"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.startQueryIntvl == "31"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.querierTimeout == "255"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.robustFac == "2"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.ver == "v2"
+ - default_igmp_intf_policy.current.0.igmpIfPol.attributes.ifCtrl == ""
+
+# UPDATE IGMP INTERFACE POLICY
+- name: Update IGMP Interface Policy
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_igmp
+ description: Updated IGMP Interface Policy
+ group_timeout: 250
+ query_interval: 150
+ query_response_interval: 7
+ last_member_count: 4
+ last_member_response: 6
+ startup_query_count: 4
+ startup_query_interval: 6
+ querier_timeout: 180
+ robustness_variable: 5
+ igmp_version: v2
+ allow_v3_asm: false
+ fast_leave: false
+ report_link_local_groups: true
+ register: update_igmp_intf_policy
+
+- name: Update IGMP Interface Policy without ifCtrl options
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_info
+ name: ansible_igmp_intf_policy
+ tenant: ansible_tenant
+ igmp_version: v3
+ register: update_igmp_no_ifctrl
+
+- name: Verify update of IGMP Interface Policy
+ ansible.builtin.assert:
+ that:
+ - update_igmp_intf_policy is changed
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.dn == "uni/tn-ansible_tenant/igmpIfPol-ansible_igmp_intf_policy"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.descr == "Updated IGMP Interface Policy"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.name == "ansible_igmp_intf_policy"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.grpTimeout == "250"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.queryIntvl == "150"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.rspIntvl == "7"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.lastMbrCnt == "4"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.lastMbrRespTime == "6"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.startQueryCnt == "4"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.startQueryIntvl == "6"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.querierTimeout == "180"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.robustFac == "5"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.ver == "v2"
+ - update_igmp_intf_policy.current.0.igmpIfPol.attributes.ifCtrl == "rep-ll"
+
+- name: Verify an update without ifCtrl options present leaves existing ifCtrl in place
+ ansible.builtin.assert:
+ that:
+ - update_igmp_no_ifctrl is changed
+ - update_igmp_no_ifctrl.current.0.igmpIfPol.attributes.ver == "v3"
+ - update_igmp_no_ifctrl.current.0.igmpIfPol.attributes.ifCtrl == "rep-ll"
+
+# QUERY IGMP INTERFACE POLICY
+- name: Query an IGMP Interface Policy
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_igmp
+ state: query
+ register: query_one
+
+- name: Query all IGMP Interface Policies
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify IGMP Interface Policy queries
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current.0.igmpIfPol.attributes.dn == "uni/tn-ansible_tenant/igmpIfPol-ansible_igmp_intf_policy"
+ - query_one.current.0.igmpIfPol.attributes.descr == "Updated IGMP Interface Policy"
+ - query_one.current.0.igmpIfPol.attributes.name == "ansible_igmp_intf_policy"
+ - query_one.current.0.igmpIfPol.attributes.grpTimeout == "250"
+ - query_one.current.0.igmpIfPol.attributes.queryIntvl == "150"
+ - query_one.current.0.igmpIfPol.attributes.rspIntvl == "7"
+ - query_one.current.0.igmpIfPol.attributes.lastMbrCnt == "4"
+ - query_one.current.0.igmpIfPol.attributes.lastMbrRespTime == "6"
+ - query_one.current.0.igmpIfPol.attributes.startQueryCnt == "4"
+ - query_one.current.0.igmpIfPol.attributes.startQueryIntvl == "6"
+ - query_one.current.0.igmpIfPol.attributes.querierTimeout == "180"
+ - query_one.current.0.igmpIfPol.attributes.robustFac == "5"
+ - query_one.current.0.igmpIfPol.attributes.ver == "v3"
+ - query_one.current.0.igmpIfPol.attributes.ifCtrl == "rep-ll"
+ - query_all is not changed
+ - query_all.current | length > 1
+
+# REMOVE IGMP INTERFACE POLICY
+- name: Delete an IGMP Interface Policy
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_igmp
+ state: absent
+ register: delete
+
+- name: Delete IGMP Interface Policy again
+ cisco.aci.aci_igmp_interface_policy:
+ <<: *aci_igmp
+ state: absent
+ register: delete_again
+
+- name: Verify deletion of IGMP Interface Policy
+ ansible.builtin.assert:
+ that:
+ - delete is changed
+ - delete_again is not changed
+ - delete.current == []
+
+# CLEAN UP
+- name: Remove the ansible_tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ name: ansible_tenant
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/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_blacklist/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml
new file mode 100644
index 000000000..d7b125267
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_blacklist/tasks/main.yml
@@ -0,0 +1,464 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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
+ test_vars_leaf: &test_vars_leaf
+ pod_id: 1
+ node_id: 1101
+ interface: 1/33
+ test_vars_spine: &test_vars_spine
+ pod_id: 1
+ node_id: 1201
+ interface: 1/33
+ test_vars_fex: &test_vars_fex
+ pod_id: 1
+ node_id: 1101
+ interface: 1/33
+ fex_id: 123
+
+- name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Spine - Clean test environment with enabled interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+
+ - name: Fex - Clean test environment with enabled interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+
+ - name: Leaf - Clean test environment with enabled interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: absent
+
+ - name: Leaf - Query outofsvc_interface_blacklist
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: query
+ register: query_leaf_int_enabled
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist is not present
+ assert:
+ that:
+ - query_leaf_int_enabled.current.0.fabricOOServicePol.children is not defined
+
+ - name: Leaf - Disable interface in check mode
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: present
+ check_mode: true
+ register: disable_leaf_int_check
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist is not created after check mode
+ assert:
+ that:
+ - disable_leaf_int_check.current.0.fabricOOServicePol.children is not defined
+
+ - name: Leaf - Disable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: present
+ register: disable_leaf_int
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist is created
+ assert:
+ that:
+ - disable_leaf_int.current|length == 1
+ - disable_leaf_int.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]"
+ - disable_leaf_int.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+ - disable_leaf_int.current.0.fabricRsOosPath.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Leaf - Disable interface again
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: present
+ register: disable_leaf_int_again
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist remains created after disabling again
+ assert:
+ that:
+ - disable_leaf_int_again is not changed
+ - disable_leaf_int_again.current|length == 1
+ - disable_leaf_int_again.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]"
+ - disable_leaf_int_again.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Leaf - Query interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: query
+ register: query_leaf_int_disabled
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist remains created after query
+ assert:
+ that:
+ - query_leaf_int_disabled is not changed
+ - query_leaf_int_disabled.current|length == 1
+ - query_leaf_int_disabled.current.0.fabricOOServicePol.children.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]"
+ - query_leaf_int_disabled.current.0.fabricOOServicePol.children.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Leaf - Enable interface in check mode
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: absent
+ check_mode: true
+ register: enable_leaf_int_check
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist remains created after check mode
+ assert:
+ that:
+ - enable_leaf_int_check.current|length == 1
+ - enable_leaf_int_check.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]"
+ - enable_leaf_int_check.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Leaf - Enable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: absent
+ register: enable_leaf_int
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist is deleted
+ assert:
+ that:
+ - enable_leaf_int.current.0.fabricOOServicePol.children is not defined
+
+ - name: Leaf - Enable interface again
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: absent
+ register: enable_leaf_int_again
+
+ - name: Leaf - Verify that outofsvc_interface_blacklist remains deleted after enabling again
+ assert:
+ that:
+ - enable_leaf_int_again is not changed
+ - enable_leaf_int_again.current.0.fabricOOServicePol.children is not defined
+
+ - name: Spine - Clean test environment with enabled interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+
+ - name: Spine - Query outofsvc_interface_blacklist
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: query
+ register: query_spine_int_enabled
+
+ - name: Spine - Verify that outofsvc_interface_blacklist is not present
+ assert:
+ that:
+ - query_spine_int_enabled.current.0.fabricOOServicePol.children is not defined
+
+ - name: Spine - Disable interface in check mode
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: present
+ check_mode: true
+ register: disable_spine_int_check
+
+ - name: Spine - Verify that outofsvc_interface_blacklist is not created after check mode
+ assert:
+ that:
+ - disable_spine_int_check.current.0.fabricOOServicePol.children is not defined
+
+ - name: Spine - Disable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: present
+ register: disable_spine_int
+
+ - name: Spine - Verify that outofsvc_interface_blacklist is created
+ assert:
+ that:
+ - disable_spine_int.current|length == 1
+ - disable_spine_int.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]"
+ - disable_spine_int.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Spine - Disable interface again
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: present
+ register: disable_spine_int_again
+
+ - name: Spine - Verify that outofsvc_interface_blacklist remains created after disabling again
+ assert:
+ that:
+ - disable_spine_int_again is not changed
+ - disable_spine_int_again.current|length == 1
+ - disable_spine_int_again.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]"
+ - disable_spine_int_again.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Spine - Query interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: query
+ register: query_spine_int_disabled
+
+ - name: Spine - Verify that outofsvc_interface_blacklist remains created after query
+ assert:
+ that:
+ - query_spine_int_disabled is not changed
+ - query_spine_int_disabled.current|length == 1
+ - query_spine_int_disabled.current.0.fabricOOServicePol.children.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]"
+ - query_spine_int_disabled.current.0.fabricOOServicePol.children.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Spine - Enable interface in check mode
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+ check_mode: true
+ register: enable_spine_int_check
+
+ - name: Spine - Verify that outofsvc_interface_blacklist remains created after check mode
+ assert:
+ that:
+ - enable_spine_int_check.current|length == 1
+ - enable_spine_int_check.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]"
+ - enable_spine_int_check.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Spine - Enable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+ register: enable_spine_int
+
+ - name: Spine - Verify that outofsvc_interface_blacklist is deleted
+ assert:
+ that:
+ - enable_spine_int.current.0.fabricOOServicePol.children is not defined
+
+ - name: Spine - Enable interface again
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+ register: enable_spine_int_again
+
+ - name: Spine - Verify that outofsvc_interface_blacklist remains deleted after enabling again
+ assert:
+ that:
+ - enable_spine_int_again is not changed
+ - enable_spine_int_again.current.0.fabricOOServicePol.children is not defined
+
+ - name: Fex - Clean test environment with enabled interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+
+ - name: Fex - Query outofsvc_interface_blacklist
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: query
+ register: query_fex_int_enabled
+
+ - name: Fex - Verify that outofsvc_interface_blacklist is not present
+ assert:
+ that:
+ - query_fex_int_enabled.current.0.fabricOOServicePol.children is not defined
+
+ - name: Fex - Disable interface in check mode
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: present
+ check_mode: true
+ register: disable_fex_int_check
+
+ - name: Fex - Verify that outofsvc_interface_blacklist is not created after check mode
+ assert:
+ that:
+ - disable_fex_int_check.current.0.fabricOOServicePol.children is not defined
+
+ - name: Fex - Disable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: present
+ register: disable_fex_int
+
+ - name: Fex - Verify that outofsvc_interface_blacklist is created
+ assert:
+ that:
+ - disable_fex_int.current|length == 1
+ - disable_fex_int.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]"
+ - disable_fex_int.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Fex - Disable interface again
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: present
+ register: disable_fex_int_again
+
+ - name: Fex - Verify that outofsvc_interface_blacklist remains created after disabling again
+ assert:
+ that:
+ - disable_fex_int_again is not changed
+ - disable_fex_int_again.current|length == 1
+ - disable_fex_int_again.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]"
+ - disable_fex_int_again.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Fex - Query interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: query
+ register: query_fex_int_disabled
+
+ - name: Fex - Verify that outofsvc_interface_blacklist remains created after query
+ assert:
+ that:
+ - query_fex_int_disabled is not changed
+ - query_fex_int_disabled.current|length == 1
+ - query_fex_int_disabled.current.0.fabricOOServicePol.children.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]"
+ - query_fex_int_disabled.current.0.fabricOOServicePol.children.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Fex - Enable interface in check mode
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+ check_mode: true
+ register: enable_fex_int_check
+
+ - name: Fex - Verify that outofsvc_interface_blacklist remains created after check mode
+ assert:
+ that:
+ - enable_fex_int_check.current|length == 1
+ - enable_fex_int_check.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]"
+ - enable_fex_int_check.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+
+ - name: Fex - Enable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+ register: enable_fex_int
+
+ - name: Fex - Verify that outofsvc_interface_blacklist is deleted
+ assert:
+ that:
+ - enable_fex_int.current.0.fabricOOServicePol.children is not defined
+
+ - name: Fex - Enable interface again
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+ register: enable_fex_int_again
+
+ - name: Fex - Verify that outofsvc_interface_blacklist remains deleted after enabling again
+ assert:
+ that:
+ - enable_fex_int_again is not changed
+ - enable_fex_int_again.current.0.fabricOOServicePol.children is not defined
+
+ - name: Leaf - Disable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: present
+
+ - name: Spine - Disable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: present
+
+ - name: Fex - Disable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: present
+
+ - name: All - Query interfaces
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ state: query
+ register: query_all_disabled
+
+ - name: All - Verify that multiple outofsvc_interface_blacklist exist
+ assert:
+ that:
+ - query_all_disabled is not changed
+ - query_all_disabled.current | length == 3
+
+ - name: Leaf - Enable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: absent
+
+ - name: Spine - Enable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+
+ - name: Fex - Enable interface
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+
+ - name: All - Query interfaces
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ state: query
+ register: query_all_enabled
+
+ - name: All - Verify that no outofsvc_interface_blacklist exist
+ assert:
+ that:
+ - query_all_enabled is not changed
+ - query_all_enabled.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/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_config/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml
new file mode 100644
index 000000000..75253bd40
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_config/tasks/main.yml
@@ -0,0 +1,680 @@
+# Test code for the ACI modules
+# Copyright: (c) 2023, Sabari Jaganathan <sajagana@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: '{{ aci_output_level | default("debug") }}'
+
+
+- name: Query system information
+ cisco.aci.aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for ACI v6+ and non-cloud sites
+ when:
+ - version.current.0.topSystem.attributes.version is version('6', '>=')
+ - query_cloud.current == [] # This condition will execute only non-cloud sites
+ block:
+ # Negative test cases
+ - name: Ensure Interface does not exists, invalid test without node id
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: switch_port
+ interface: "1/1/1"
+ state: absent
+ register: invalid_interface_absent
+ ignore_errors: true
+
+ - name: Ensure Interface 501 does not exists, invalid test with invalid interface details
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: switch_port
+ node: 501
+ interface: "a/b/c"
+ state: absent
+ register: invalid_interface_details
+ ignore_errors: true
+
+ - name: Add Interface 501, invalid test with policy_group and breakout
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: switch_port
+ policy_group: ans_test_switch_port
+ node: 501
+ breakout: "100g-4x"
+ interface: "1/1/1"
+ state: present
+ register: invalid_policy_group_with_breakout
+ ignore_errors: true
+
+ - name: Assertions check for the invalid tasks
+ assert:
+ that:
+ - invalid_interface_absent.msg is match("state is absent but all of the following are missing{{':'}} node")
+ - invalid_interface_details is not changed
+ - invalid_interface_details.msg is match("Interface configuration failed due to")
+ - invalid_policy_group_with_breakout is not changed
+ - invalid_policy_group_with_breakout.msg == "parameters are mutually exclusive{{':'}} policy_group|breakout"
+
+ - name: Invalid Node ID check
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: 5000
+ interface: "1/1/1"
+ state: present
+ register: invalid_node
+ ignore_errors: true
+
+ - name: Invalid Interface ID check
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: 101
+ interface: "1"
+ state: present
+ register: invalid_interface
+ ignore_errors: true
+
+ - name: Invalid Card ID check
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: 101
+ interface: "1000/1/1"
+ state: present
+ register: invalid_card
+ ignore_errors: true
+
+ - name: Invalid Port ID check
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: 101
+ interface: "1/500/1"
+ state: present
+ register: invalid_port
+ ignore_errors: true
+
+ - name: Invalid Sub Port ID check
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: 101
+ interface: "1/1/100"
+ state: present
+ register: invalid_sub_port
+ ignore_errors: true
+
+ - name: Assertions check for invalid interface configuration tasks
+ assert:
+ that:
+ - invalid_node is not changed
+ - invalid_node.msg is match("^Node ID{{':'}} .+? is invalid; it must be in the range of 101 to 4000.")
+ - invalid_interface is not changed
+ - invalid_interface.msg is match("^Interface{{':'}} .+? is invalid; The format must be either card\/port\/sub_port\(1\/1\/1\) or card\/port\(1\/1\)")
+ - invalid_card is not changed
+ - invalid_card.msg is match("^Card ID{{':'}} .+? is invalid; it must be in the range of 1 to 64.")
+ - invalid_port is not changed
+ - invalid_port.msg is match("^Port ID{{':'}} .+? is invalid; it must be in the range of 1 to 128.")
+ - 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
+ cisco.aci.aci_interface_config: &interface_501_absent
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: switch_port
+ policy_group: ans_test_switch_port
+ node: 501
+ interface: "1/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
+ 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
+ cisco.aci.aci_interface_config: &nm_interface_501_present
+ <<: *interface_501_absent
+ state: present
+ register: nm_interface_501_present
+
+ - name: Assertions check for an interface 501
+ assert:
+ that:
+ - interface_501_absent.current == []
+ - cm_interface_501_present is changed
+ - cm_interface_501_present.current == []
+ - nm_interface_501_present is changed
+ - 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.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"
+
+ - name: Ensure Interface 502 with leaf access with policy_group - pc_or_vpc absent
+ cisco.aci.aci_interface_config: &interface_502_absent
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: pc_or_vpc
+ policy_group: ans_test_pc_or_vpc
+ node: 502
+ interface: "2/2/2"
+ description: "Interface - 502 added by Ansible"
+ state: absent
+ register: interface_502_absent
+
+ - name: Ensure Interface 502 with leaf access with policy_group - pc_or_vpc present - check mode
+ cisco.aci.aci_interface_config: &cm_interface_502_present
+ <<: *interface_502_absent
+ state: present
+ check_mode: true
+ register: cm_interface_502_present
+
+ - name: Ensure Interface 502 with leaf access with policy_group - pc_or_vpc present - normal mode
+ cisco.aci.aci_interface_config: &nm_interface_502_present
+ <<: *interface_502_absent
+ state: present
+ register: nm_interface_502_present
+
+ - name: Assertions check for an interface 502
+ assert:
+ that:
+ - interface_502_absent.current == []
+ - cm_interface_502_present is changed
+ - cm_interface_502_present.current == []
+ - nm_interface_502_present is changed
+ - nm_interface_502_present.current != []
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.assocGrp == "uni/infra/funcprof/accbundle-ans_test_pc_or_vpc"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.brkoutMap == "none"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.card == "2"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.description == "Interface - 502 added by Ansible"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-502-card-2-port-2-sub-2"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.node == "502"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.port == "2"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.role == "leaf"
+ - nm_interface_502_present.current.0.infraPortConfig.attributes.shutdown == "no"
+
+ - name: Ensure Interface 505 with leaf access with policy_group - fc absent
+ cisco.aci.aci_interface_config: &interface_505_absent
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: fc
+ policy_group: ans_test_fc
+ node: 505
+ interface: "5/5/5"
+ description: "Interface - 505 added by Ansible"
+ state: absent
+ register: interface_505_absent
+
+ - name: Ensure Interface 505 with leaf access with policy_group - fc present - check mode
+ cisco.aci.aci_interface_config: &cm_interface_505_present
+ <<: *interface_505_absent
+ state: present
+ check_mode: true
+ register: cm_interface_505_present
+
+ - name: Ensure Interface 505 with leaf access with policy_group - fc present - normal mode
+ cisco.aci.aci_interface_config: &nm_interface_505_present
+ <<: *interface_505_absent
+ state: present
+ register: nm_interface_505_present
+
+ - name: Assertions check for an interface 505
+ assert:
+ that:
+ - interface_505_absent.current == []
+ - cm_interface_505_present is changed
+ - cm_interface_505_present.current == []
+ - nm_interface_505_present is changed
+ - nm_interface_505_present.current != []
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.assocGrp == "uni/infra/funcprof/fcaccportgrp-ans_test_fc"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.brkoutMap == "none"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.card == "5"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.description == "Interface - 505 added by Ansible"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-505-card-5-port-5-sub-5"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.node == "505"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.port == "5"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.role == "leaf"
+ - nm_interface_505_present.current.0.infraPortConfig.attributes.shutdown == "no"
+
+ - name: Ensure Interface 506 with leaf access with policy_group - fc_port_channel absent
+ cisco.aci.aci_interface_config: &interface_506_absent
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: fc_port_channel
+ policy_group: ans_test_fc_port_channel
+ node: 506
+ interface: "6/6/6"
+ description: "Interface - 506 added by Ansible"
+ state: absent
+ register: interface_506_absent
+
+ - name: Ensure Interface 506 with leaf access with policy_group - fc_port_channel present - check mode
+ cisco.aci.aci_interface_config: &cm_interface_506_present
+ <<: *interface_506_absent
+ state: present
+ check_mode: true
+ register: cm_interface_506_present
+
+ - name: Ensure Interface 506 with leaf access with policy_group - fc_port_channel present - normal mode
+ cisco.aci.aci_interface_config: &nm_interface_506_present
+ <<: *interface_506_absent
+ state: present
+ register: nm_interface_506_present
+
+ - name: Assertions check for an interface 506
+ assert:
+ that:
+ - interface_506_absent.current == []
+ - cm_interface_506_present is changed
+ - cm_interface_506_present.current == []
+ - nm_interface_506_present is changed
+ - nm_interface_506_present.current != []
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.assocGrp == "uni/infra/funcprof/fcaccbundle-ans_test_fc_port_channel"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.brkoutMap == "none"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.card == "6"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.description == "Interface - 506 added by Ansible"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-506-card-6-port-6-sub-6"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.node == "506"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.port == "6"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.role == "leaf"
+ - nm_interface_506_present.current.0.infraPortConfig.attributes.shutdown == "no"
+
+ - name: Ensure Interface 507 with leaf fabric with policy_group - leaf_fabric absent
+ cisco.aci.aci_interface_config: &interface_507_absent
+ <<: *aci_info
+ role: leaf
+ port_type: fabric
+ interface_type: leaf_fabric
+ policy_group: ans_test_leaf_fabric
+ node: 507
+ interface: "7/7/7"
+ description: "Interface - 507 added by Ansible"
+ state: absent
+ register: interface_507_absent
+
+ - name: Ensure Interface 507 with leaf fabric with policy_group - leaf_fabric present - check mode
+ cisco.aci.aci_interface_config: &cm_interface_507_present
+ <<: *interface_507_absent
+ state: present
+ check_mode: true
+ register: cm_interface_507_present
+
+ - name: Ensure Interface 507 with leaf fabric with policy_group - leaf_fabric present - normal mode
+ cisco.aci.aci_interface_config: &nm_interface_507_present
+ <<: *interface_507_absent
+ state: present
+ register: nm_interface_507_present
+
+ - name: Assertions check for an interface 507
+ assert:
+ that:
+ - interface_507_absent.current == []
+ - cm_interface_507_present is changed
+ - cm_interface_507_present.current == []
+ - nm_interface_507_present is changed
+ - nm_interface_507_present.current != []
+ - nm_interface_507_present.current.0.fabricPortConfig.attributes.assocGrp == "uni/fabric/funcprof/leportgrp-ans_test_leaf_fabric"
+ - nm_interface_507_present.current.0.fabricPortConfig.attributes.description == "Interface - 507 added by Ansible"
+ - nm_interface_507_present.current.0.fabricPortConfig.attributes.dn == "uni/fabric/portconfnode-507-card-7-port-7-sub-7"
+ - nm_interface_507_present.current.0.fabricPortConfig.attributes.role == "leaf"
+ - nm_interface_507_present.current.0.fabricPortConfig.attributes.shutdown == "no"
+
+ - name: Ensure Interface 508 with spine access with policy_group - spine_access absent
+ cisco.aci.aci_interface_config: &interface_508_absent
+ <<: *aci_info
+ role: spine
+ port_type: access
+ interface_type: spine_access
+ policy_group: ans_test_spine_access
+ node: 508
+ interface: "8/8/8"
+ description: "Interface - 508 added by Ansible"
+ state: absent
+ register: interface_508_absent
+
+ - name: Ensure Interface 508 with spine access with policy_group - spine_access present - check mode
+ cisco.aci.aci_interface_config: &cm_interface_508_present
+ <<: *interface_508_absent
+ state: present
+ check_mode: true
+ register: cm_interface_508_present
+
+ - name: Ensure Interface 508 with spine access with policy_group - spine_access present - normal mode
+ cisco.aci.aci_interface_config: &nm_interface_508_present
+ <<: *interface_508_absent
+ state: present
+ register: nm_interface_508_present
+
+ - name: Assertions check for an interface 508
+ assert:
+ that:
+ - interface_508_absent.current == []
+ - cm_interface_508_present is changed
+ - cm_interface_508_present.current == []
+ - nm_interface_508_present is changed
+ - nm_interface_508_present.current != []
+ - nm_interface_508_present.current.0.infraPortConfig.attributes.assocGrp == "uni/infra/funcprof/spaccportgrp-ans_test_spine_access"
+ - nm_interface_508_present.current.0.infraPortConfig.attributes.description == "Interface - 508 added by Ansible"
+ - nm_interface_508_present.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-508-card-8-port-8-sub-8"
+ - nm_interface_508_present.current.0.infraPortConfig.attributes.role == "spine"
+ - nm_interface_508_present.current.0.infraPortConfig.attributes.shutdown == "no"
+
+ - name: Ensure Interface 509 with spine fabric with policy_group - spine_fabric absent
+ cisco.aci.aci_interface_config: &interface_509_absent
+ <<: *aci_info
+ role: spine
+ port_type: fabric
+ interface_type: spine_fabric
+ policy_group: ans_test_spine_fabric
+ node: 509
+ interface: "9/9/9"
+ description: "Interface - 509 added by Ansible"
+ state: absent
+ register: interface_509_absent
+
+ - name: Ensure Interface 509 with spine fabric with policy_group - spine_fabric present - check mode
+ cisco.aci.aci_interface_config: &cm_interface_509_present
+ <<: *interface_509_absent
+ state: present
+ check_mode: true
+ register: cm_interface_509_present
+
+ - name: Ensure Interface 509 with spine fabric with policy_group - spine_fabric present - normal mode
+ cisco.aci.aci_interface_config: &nm_interface_509_present
+ <<: *interface_509_absent
+ state: present
+ register: nm_interface_509_present
+
+ - name: Ensure Interface 509 with spine fabric with policy_group - spine_fabric present - normal mode with idempotency check
+ cisco.aci.aci_interface_config:
+ <<: *interface_509_absent
+ state: present
+ register: idm_interface_509_present
+
+ - name: Assertions check for an interface 509
+ assert:
+ that:
+ - interface_509_absent.current == []
+ - cm_interface_509_present is changed
+ - cm_interface_509_present.current == []
+ - nm_interface_509_present is changed
+ - nm_interface_509_present.current != []
+ - nm_interface_509_present.current.0.fabricPortConfig.attributes.assocGrp == "uni/fabric/funcprof/spportgrp-ans_test_spine_fabric"
+ - nm_interface_509_present.current.0.fabricPortConfig.attributes.description == "Interface - 509 added by Ansible"
+ - nm_interface_509_present.current.0.fabricPortConfig.attributes.dn == "uni/fabric/portconfnode-509-card-9-port-9-sub-9"
+ - nm_interface_509_present.current.0.fabricPortConfig.attributes.role == "spine"
+ - nm_interface_509_present.current.0.fabricPortConfig.attributes.shutdown == "no"
+ - idm_interface_509_present is not changed
+ - idm_interface_509_present.current != []
+ - idm_interface_509_present.current.0.fabricPortConfig.attributes.assocGrp == "uni/fabric/funcprof/spportgrp-ans_test_spine_fabric"
+ - idm_interface_509_present.current.0.fabricPortConfig.attributes.description == "Interface - 509 added by Ansible"
+ - idm_interface_509_present.current.0.fabricPortConfig.attributes.dn == "uni/fabric/portconfnode-509-card-9-port-9-sub-9"
+ - idm_interface_509_present.current.0.fabricPortConfig.attributes.role == "spine"
+ - idm_interface_509_present.current.0.fabricPortConfig.attributes.shutdown == "no"
+
+ # Breakout part begins
+ - name: Convert the interface 501 to breakout(100g-4x) with policy group - invalid test
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: switch_port
+ policy_group: ans_test_switch_port
+ breakout: "100g-4x"
+ node: 501
+ interface: "1/1/1"
+ description: "Interface - 501 added by Ansible"
+ state: present
+ register: invalid_breakout_501_present
+ ignore_errors: true
+
+ - name: Convert the interface 501 to breakout(100g-4x) - check mode
+ cisco.aci.aci_interface_config: &valid_breakout_501_present
+ <<: *aci_info
+ role: leaf
+ port_type: access
+ interface_type: switch_port
+ breakout: "100g-4x"
+ node: 501
+ interface: "1/1/1"
+ description: "Interface - 501 added by Ansible"
+ admin_state: "down"
+ state: present
+ check_mode: true
+ register: cm_valid_breakout_501_present
+
+ - name: Convert the interface 501 to breakout(100g-4x) - normal mode
+ cisco.aci.aci_interface_config:
+ <<: *valid_breakout_501_present
+ register: nm_valid_breakout_501_present
+
+ - name: Convert the interface 501 to breakout(100g-4x) - normal mode with idempotency check
+ cisco.aci.aci_interface_config:
+ <<: *valid_breakout_501_present
+ register: idm_breakout_501_present
+
+ - name: Assertions check for convert the interface 501 to breakout(100g-4x)
+ assert:
+ that:
+ - invalid_breakout_501_present is not changed
+ - invalid_breakout_501_present.msg == "parameters are mutually exclusive{{':'}} policy_group|breakout"
+ - cm_valid_breakout_501_present is changed
+ - cm_valid_breakout_501_present.current != []
+ - cm_valid_breakout_501_present.current.0.infraPortConfig.attributes.brkoutMap == "none"
+ - nm_valid_breakout_501_present is changed
+ - 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.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.role == "leaf"
+ - idm_breakout_501_present.current.0.infraPortConfig.attributes.shutdown == "yes"
+ # Breakup part ends
+
+ - name: Query all access interfaces
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ port_type: access
+ state: query
+ register: query_all_access_interfaces
+
+ - name: Assertions check for query all access interfaces
+ assert:
+ that:
+ - query_all_access_interfaces is not changed
+ - query_all_access_interfaces.current|length >= 6
+
+ - name: Query all fabric interfaces
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ port_type: fabric
+ state: query
+ register: query_all_fabric_interfaces
+
+ - name: Assertions check for query all fabric interfaces
+ assert:
+ that:
+ - query_all_fabric_interfaces is not changed
+ - query_all_fabric_interfaces.current|length >= 2
+
+ - name: Query a access interface with node id 502
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ port_type: access
+ node: 502
+ state: query
+ register: query_access_interface_502
+
+ - name: Assertions check for query a access interface with node id 502
+ assert:
+ that:
+ - query_access_interface_502 is not changed
+ - query_access_interface_502.current|length == 1
+ - query_access_interface_502.current.0.infraPortConfig.attributes.brkoutMap == "none"
+ - query_access_interface_502.current.0.infraPortConfig.attributes.description == "Interface - 502 added by Ansible"
+ - query_access_interface_502.current.0.infraPortConfig.attributes.dn == "uni/infra/portconfnode-502-card-2-port-2-sub-2"
+ - query_access_interface_502.current.0.infraPortConfig.attributes.role == "leaf"
+ - query_access_interface_502.current.0.infraPortConfig.attributes.shutdown == "no"
+
+ - name: Query a fabric interface with node id 509
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ port_type: fabric
+ node: 509
+ state: query
+ register: query_access_fabric_509
+
+ - name: Assertions check for query a fabric interface with node id 509
+ assert:
+ that:
+ - query_access_fabric_509 is not changed
+ - query_access_fabric_509.current|length == 1
+ - query_access_fabric_509.current.0.fabricPortConfig.attributes.assocGrp == "uni/fabric/funcprof/spportgrp-ans_test_spine_fabric"
+ - query_access_fabric_509.current.0.fabricPortConfig.attributes.description == "Interface - 509 added by Ansible"
+ - query_access_fabric_509.current.0.fabricPortConfig.attributes.dn == "uni/fabric/portconfnode-509-card-9-port-9-sub-9"
+ - query_access_fabric_509.current.0.fabricPortConfig.attributes.role == "spine"
+ - query_access_fabric_509.current.0.fabricPortConfig.attributes.shutdown == "no"
+
+ - name: Ensure Breakout Interface 501 absent
+ cisco.aci.aci_interface_config:
+ <<: *valid_breakout_501_present
+ state: absent
+ register: rm_interface_501_present
+
+ - name: Ensure Interface 502 with leaf access with policy_group - pc_or_vpc absent
+ cisco.aci.aci_interface_config:
+ <<: *interface_502_absent
+ state: absent
+ register: rm_interface_502_present
+
+ - name: Ensure Interface 505 with leaf access with policy_group - fc absent
+ cisco.aci.aci_interface_config:
+ <<: *interface_505_absent
+ state: absent
+ register: rm_interface_505_present
+
+ - name: Ensure Interface 506 with leaf access with policy_group - fc_port_channel absent
+ cisco.aci.aci_interface_config:
+ <<: *interface_506_absent
+ state: absent
+ register: rm_interface_506_present
+
+ - name: Ensure Interface 507 with leaf fabric with policy_group - leaf_fabric absent
+ cisco.aci.aci_interface_config:
+ <<: *interface_507_absent
+ state: absent
+ register: rm_interface_507_present
+
+ - name: Ensure Interface 508 with spine access with policy_group - spine_access absent
+ cisco.aci.aci_interface_config:
+ <<: *interface_508_absent
+ state: absent
+ register: rm_interface_508_present
+
+ - name: Assertions check for remove Interfaces 501 to 508
+ assert:
+ that:
+ - rm_interface_501_present is changed
+ - rm_interface_501_present.current == []
+ - rm_interface_502_present is changed
+ - rm_interface_502_present.current == []
+ - rm_interface_505_present is changed
+ - rm_interface_505_present.current == []
+ - rm_interface_506_present is changed
+ - rm_interface_506_present.current == []
+ - rm_interface_507_present is changed
+ - rm_interface_507_present.current == []
+ - rm_interface_508_present is changed
+ - rm_interface_508_present.current == []
+
+ - name: Ensure Interface 509 with spine fabric with policy_group - spine_fabric absent - check mode
+ cisco.aci.aci_interface_config:
+ <<: *interface_509_absent
+ state: absent
+ check_mode: true
+ register: cm_rm_interface_509_present
+
+ - name: Ensure Interface 509 with spine fabric with policy_group - spine_fabric absent - normal mode
+ cisco.aci.aci_interface_config:
+ <<: *interface_509_absent
+ state: absent
+ register: nm_rm_interface_509_present
+
+ - name: Assertions check for remove Interface 509
+ assert:
+ that:
+ - cm_rm_interface_509_present is changed
+ - cm_rm_interface_509_present.current != []
+ - nm_rm_interface_509_present is changed
+ - nm_rm_interface_509_present.current == []
+
+ - name: Ensure Interface 509 with spine fabric with policy_group - spine_fabric absent - normal mode with idempotency check
+ cisco.aci.aci_interface_config:
+ <<: *interface_509_absent
+ state: absent
+ register: idm_rm_interface_509_present
+
+ - name: Assertions check for remove Interface 509 with idempotency check
+ assert:
+ that:
+ - idm_rm_interface_509_present is not changed
+ - idm_rm_interface_509_present.current == []
+
+ - name: Query an interface 509 after removed from the APIC
+ cisco.aci.aci_interface_config:
+ <<: *aci_info
+ node: 509
+ port_type: "fabric"
+ state: query
+ register: query_interface_509
+
+ - name: Assertions check for query an interface 509 after removed from the APIC
+ assert:
+ that:
+ - query_interface_509 is not changed
+ - query_interface_509.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/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_description/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml
new file mode 100644
index 000000000..ec4f0250d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_description/tasks/main.yml
@@ -0,0 +1,289 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# 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: Node types
+ set_fact:
+ test_vars_leaf: &test_vars_leaf
+ pod_id: 1
+ node_id: 1101
+ node_type: leaf
+ interface: 1/33
+ description: testing
+ test_vars_spine: &test_vars_spine
+ pod_id: 1
+ node_id: 1201
+ node_type: spine
+ interface: 1/33
+ description: testing
+ test_vars_fex: &test_vars_fex
+ pod_id: 1
+ node_id: 1101
+ interface: 1/33
+ fex_id: 123
+ description: testing
+
+- 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: Leaf - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: absent
+
+ - name: Spine - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+
+ - name: Fex - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+
+ - name: Leaf - Query interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: query
+ register: query_leaf_description
+
+ - name: Leaf - Verify that no infraHPathS is present
+ assert:
+ that:
+ - query_leaf_description.current.0.infraInfra.children.0.infraHPathS.children is not defined
+
+ - name: Leaf - Set description on interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: present
+ register: set_leaf_description
+
+ - name: Leaf - Verify that description is set on interface
+ assert:
+ that:
+ - set_leaf_description.current|length == 1
+ - set_leaf_description.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/33]"
+ - set_leaf_description.current.0.infraHPathS.attributes.descr == "testing"
+ - set_leaf_description.current.0.infraHPathS.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Query Leaf interface - 1101_eth1_33
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: query
+ register: query_leaf_interface_1101_eth1_33
+
+ - name: Assertion check for query Leaf interface - 1101_eth1_33
+ assert:
+ that:
+ - query_leaf_interface_1101_eth1_33.current.0.infraHPathS.children | length == 1
+ - query_leaf_interface_1101_eth1_33.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.rn == "rsHPathAtt-[topology/pod-1/paths-1101/pathep-[eth1/33]]"
+ - query_leaf_interface_1101_eth1_33.current.0.infraHPathS.attributes.dn == "uni/infra/hpaths-1101_eth1_33"
+ - query_leaf_interface_1101_eth1_33.current.0.infraHPathS.attributes.descr == "testing"
+ - query_leaf_interface_1101_eth1_33.current.0.infraHPathS.attributes.name == "1101_eth1_33"
+
+ - name: Query all leaf interfaces
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ node_type: leaf
+ state: query
+ register: query_all_leaf_interfaces
+
+ - name: Verify query all leaf interfaces
+ assert:
+ that:
+ - query_all_leaf_interfaces.current | length > 1
+ - query_all_leaf_interfaces.current.1.infraHPathS.children.0.infraRsHPathAtt.attributes.rn == "rsHPathAtt-[topology/pod-1/paths-1101/pathep-[eth1/33]]"
+ - query_all_leaf_interfaces.current.1.infraHPathS.attributes.dn == "uni/infra/hpaths-1101_eth1_33"
+ - query_all_leaf_interfaces.current.1.infraHPathS.attributes.descr == "testing"
+ - query_all_leaf_interfaces.current.1.infraHPathS.attributes.name == "1101_eth1_33"
+
+ - name: Leaf - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: absent
+
+ - name: Leaf - Query interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_leaf
+ state: query
+ register: query_leaf_description_again
+
+ - name: Leaf - Verify that no infraHPathS is present
+ assert:
+ that:
+ - query_leaf_description_again.current.0.infraInfra.children.0.infraHPathS.children is not defined
+
+ - name: Spine - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+
+ - name: Spine - Query interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: query
+ register: query_spine_description
+
+ - name: Spine - Verify that no infraSHPathS is present
+ assert:
+ that:
+ - query_spine_description.current.0.infraInfra.children.0.infraSHPathS.children is not defined
+
+ - name: Spine - Set description on interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: present
+ register: set_spine_description
+
+ - name: Spine - Verify that description is set on interface
+ assert:
+ that:
+ - set_spine_description.current|length == 1
+ - set_spine_description.current.0.infraSHPathS.children.0.infraRsSHPathAtt.attributes.tDn == "topology/pod-1/paths-1201/pathep-[eth1/33]"
+ - set_spine_description.current.0.infraSHPathS.attributes.descr == "testing"
+
+ - name: Query Spine interface - 1201_eth1_33
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: query
+ register: query_spine_interface_1201_eth1_33
+
+ - name: Assertion check for query Spine interface - 1201_eth1_33
+ assert:
+ that:
+ - query_spine_interface_1201_eth1_33.current.0.infraSHPathS.children | length == 1
+ - query_spine_interface_1201_eth1_33.current.0.infraSHPathS.children.0.infraRsSHPathAtt.attributes.rn == "rsSHPathAtt-[topology/pod-1/paths-1201/pathep-[eth1/33]]"
+ - query_spine_interface_1201_eth1_33.current.0.infraSHPathS.attributes.dn == "uni/infra/shpaths-1201_eth1_33"
+ - query_spine_interface_1201_eth1_33.current.0.infraSHPathS.attributes.descr == "testing"
+ - query_spine_interface_1201_eth1_33.current.0.infraSHPathS.attributes.name == "1201_eth1_33"
+
+ - name: Query all spine interfaces
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ node_type: spine
+ state: query
+ register: query_all_spine_interfaces
+
+ - name: Verify query all spine interfaces
+ assert:
+ that:
+ - query_all_spine_interfaces.current | length >= 1
+ - query_all_spine_interfaces.current.1.infraSHPathS.children.0.infraRsSHPathAtt.attributes.rn == "rsSHPathAtt-[topology/pod-1/paths-1201/pathep-[eth1/33]]"
+ - query_all_spine_interfaces.current.1.infraSHPathS.attributes.dn == "uni/infra/shpaths-1201_eth1_33"
+ - query_all_spine_interfaces.current.1.infraSHPathS.attributes.descr == "testing"
+ - query_all_spine_interfaces.current.1.infraSHPathS.attributes.name == "1201_eth1_33"
+
+ - name: Spine - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: absent
+
+ - name: Spine - Query interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_spine
+ state: query
+ register: query_spine_description_again
+
+ - name: Spine - Verify that no infraSHPathS is present
+ assert:
+ that:
+ - query_spine_description_again.current.0.infraInfra.children.0.infraSHPathS.children is not defined
+
+ - name: Fex - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+
+ - name: Fex - Query interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: query
+ register: query_fex_description
+
+ - name: Fex - Verify that no infraHPathS is present
+ assert:
+ that:
+ - query_fex_description.current.0.infraInfra.children.0.infraHPathS.children is not defined
+
+ - name: Fex - Set description on interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: present
+ register: set_fex_description
+
+ - name: Fex - Verify that description is set on interface
+ assert:
+ that:
+ - set_fex_description.current|length == 1
+ - set_fex_description.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.tDn == "topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]"
+ - set_fex_description.current.0.infraHPathS.attributes.descr == "testing"
+
+ - name: Query Fex interface - 1101_eth123_1_33
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: query
+ register: query_fex_interface_1201_eth1_33
+
+ - name: Assertion check for query Fex interface - 1101_eth123_1_33
+ assert:
+ that:
+ - query_fex_interface_1201_eth1_33.current.0.infraHPathS.children | length == 1
+ - query_fex_interface_1201_eth1_33.current.0.infraHPathS.children.0.infraRsHPathAtt.attributes.rn == "rsHPathAtt-[topology/pod-1/paths-1101/extpaths-123/pathep-[eth1/33]]"
+ - query_fex_interface_1201_eth1_33.current.0.infraHPathS.attributes.descr == "testing"
+ - query_fex_interface_1201_eth1_33.current.0.infraHPathS.attributes.name == "1101_eth123_1_33"
+
+ - name: Fex - Clean test environment with no description interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: absent
+
+ - name: Fex - Query interface
+ cisco.aci.aci_interface_description:
+ <<: *aci_info
+ <<: *test_vars_fex
+ state: query
+ register: query_fex_description_again
+
+ - name: Fex - Verify that no infraHPathS is present
+ assert:
+ that:
+ - query_fex_description_again.current.0.infraInfra.children.0.infraHPathS.children is not defined
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases
new file mode 100644
index 000000000..cf765b70b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases
@@ -0,0 +1 @@
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml
new file mode 100644
index 000000000..48ac1d806
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml
@@ -0,0 +1,111 @@
+# Test code for the ACI modules
+# Copyright: (c) 2019, Tim Knipper (tknipper11) <tim.knipper@gmail.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: 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: Remove CDP Test Policy
+ cisco.aci.aci_interface_policy_cdp:
+ name: Ansible_CDP_Test_Policy
+ 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(false) }}'
+ output_level: debug
+ state: absent
+ register: cdp_delete
+
+ - name: Create CDP Test Policy
+ cisco.aci.aci_interface_policy_cdp:
+ name: Ansible_CDP_Test_Policy
+ 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(false) }}'
+ # output_level: debug
+ state: present
+ register: cdp_create
+ - debug:
+ var: cdp_create
+
+ - assert:
+ that:
+ - cdp_create is changed
+ - cdp_create.current.0.cdpIfPol.attributes.annotation == 'orchestrator:ansible'
+
+
+ - name: test for idempotency
+ cisco.aci.aci_interface_policy_cdp:
+ name: Ansible_CDP_Test_Policy
+ 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(false) }}'
+ # output_level: debug
+ state: present
+ register: cdp_idem
+
+ - name: Assert that idempotency is not changed
+ assert:
+ that:
+ - cdp_idem is not changed
+
+
+
+ - name: Create CDP Disable Test Policy
+ cisco.aci.aci_interface_policy_cdp:
+ name: Ansible_CDP_Test_Policy
+ 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(false) }}'
+ # output_level: debug
+ state: present
+ admin_state: false
+ register: cdp_disable
+ - debug:
+ var: cdp_disable
+
+ - name: Assert that CDP is Disabled
+ assert:
+ that:
+ - cdp_disable.current.0.cdpIfPol.attributes.adminSt == 'disabled'
+
+
+ - name: Query CDP Policy
+ cisco.aci.aci_interface_policy_cdp:
+ 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(false) }}'
+ # output_level: debug
+ state: query
+ register: cdp_query
+ - debug:
+ var: cdp_query
+
+ - name: CDP Query Assertion
+ assert:
+ that:
+ - cdp_query is not changed \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_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_breakout_port_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml
new file mode 100644
index 000000000..b84f64b9a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml
@@ -0,0 +1,169 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_password }}'
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("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 execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Making sure leaf breakout port group doesn't exist at beginning of test
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: '{{ item }}'
+ state: absent
+ loop:
+ - 'ansible_breakout_port'
+ - 'ansible_breakout_port_2'
+
+ - name: Create leaf breakout port group (check_mode)
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port
+ description: description for ansible_breakout_port
+ breakout_map: 10g-4x
+ state: present
+ check_mode: true
+ register: cm_create_brkout_port
+
+ - name: Create leaf breakout port group (normal_mode)
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port
+ description: description for ansible_breakout_port
+ breakout_map: 10g-4x
+ state: present
+ register: nm_create_brkout_port
+
+ - name: Verify cm_create_brkout_port and nm_create_brkout_port
+ assert:
+ that:
+ - cm_create_brkout_port is changed
+ - cm_create_brkout_port.previous == []
+ - cm_create_brkout_port.proposed.infraBrkoutPortGrp.attributes.name == "ansible_breakout_port"
+ - cm_create_brkout_port.proposed.infraBrkoutPortGrp.attributes.dn == "uni/infra/funcprof/brkoutportgrp-ansible_breakout_port"
+ - cm_create_brkout_port.proposed.infraBrkoutPortGrp.attributes.descr == "description for ansible_breakout_port"
+ - cm_create_brkout_port.proposed.infraBrkoutPortGrp.attributes.brkoutMap == "10g-4x"
+ - nm_create_brkout_port is changed
+ - nm_create_brkout_port.previous == []
+ - nm_create_brkout_port.current.0.infraBrkoutPortGrp.attributes.name == "ansible_breakout_port"
+ - nm_create_brkout_port.current.0.infraBrkoutPortGrp.attributes.dn == "uni/infra/funcprof/brkoutportgrp-ansible_breakout_port"
+ - nm_create_brkout_port.current.0.infraBrkoutPortGrp.attributes.descr == "description for ansible_breakout_port"
+ - nm_create_brkout_port.current.0.infraBrkoutPortGrp.attributes.brkoutMap == "10g-4x"
+ - nm_create_brkout_port.current.0.infraBrkoutPortGrp.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Create leaf breakout port group again (normal_mode)
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port
+ description: description for ansible_breakout_port
+ breakout_map: 10g-4x
+ state: present
+ register: nm_create_brkout_port_again
+
+ - name: Verify nm_create_brkout_port_again
+ assert:
+ that:
+ - nm_create_brkout_port_again is not changed
+
+ - name: Create another leaf breakout port group
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port_2
+ state: present
+ register: nm_create_another_brkout_port
+
+ - name: Verify nm_create_another_brkout_port
+ assert:
+ that:
+ - nm_create_another_brkout_port is changed
+ - nm_create_another_brkout_port.previous == []
+ - nm_create_another_brkout_port.proposed.infraBrkoutPortGrp.attributes.name == "ansible_breakout_port_2"
+ - nm_create_another_brkout_port.proposed.infraBrkoutPortGrp.attributes.dn == "uni/infra/funcprof/brkoutportgrp-ansible_breakout_port_2"
+ - nm_create_another_brkout_port.current.0.infraBrkoutPortGrp.attributes.dn == "uni/infra/funcprof/brkoutportgrp-ansible_breakout_port_2"
+ - nm_create_another_brkout_port.current.0.infraBrkoutPortGrp.attributes.brkoutMap == "none"
+ - nm_create_another_brkout_port.current.0.infraBrkoutPortGrp.attributes.name == "ansible_breakout_port_2"
+
+ - name: Query all breakout ports
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify query_all
+ assert:
+ that:
+ query_all.current | length >= 2
+
+ - name: Query specific breakout port
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port
+ state: query
+ register: query_one
+
+ - name: Verify query_one
+ assert:
+ that:
+ - query_one is not changed
+ - query_one.current.0.infraBrkoutPortGrp.attributes.name == "ansible_breakout_port"
+
+ - name: Update breakout port
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port
+ breakout_map: none
+ description: ""
+ state: present
+ register: change_ansible_breakout_port
+
+ - name: Verify change_ansible_breakout_port
+ assert:
+ that:
+ - change_ansible_breakout_port is changed
+ - change_ansible_breakout_port.current.0.infraBrkoutPortGrp.attributes.brkoutMap == "none"
+ - change_ansible_breakout_port.current.0.infraBrkoutPortGrp.attributes.descr == ""
+
+ - name: Delete breakout port
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port
+ state: absent
+ register: rm_breakout_port
+
+ - name: Verify rm_breakout_port
+ assert:
+ that:
+ - rm_breakout_port is changed
+ - rm_breakout_port.current == []
+
+ - name: Query removed breakout port
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ <<: *aci_info
+ breakout_port_group: ansible_breakout_port
+ state: query
+ register: query_removed_breakout_port
+
+ - name: Verify query_removed_breakout_port
+ assert:
+ that:
+ - query_removed_breakout_port.current == [] \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_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_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml
new file mode 100644
index 000000000..f94ba4e48
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml
@@ -0,0 +1,460 @@
+# Test code for the ACI modules
+# 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)
+
+- 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
+ 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
+ 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
+ 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
+ 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
+ policy_group: policygroupname_link
+ lag_type: link
+ link_level_policy: linklevelpolicy
+ fibre_channel_interface_policy: fiberchannelpolicy
+ state: present
+ check_mode: true
+ register: intf_policy_leaf_polgrp_check_mode_present
+
+ - name: Adding a interface policy leaf policy group (PC) - creation works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_present
+ register: intf_policy_leaf_polgrp_present
+
+ - name: Adding a interface policy leaf policy group (PC) - idempotency works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_present
+ register: intf_policy_leaf_polgrp_idempotent
+
+ - name: Adding a interface policy leaf policy group description (PC) - update works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_present
+ description: policygroup description
+ register: intf_policy_leaf_polgrp_update
+
+ # TODO: also test for errors
+ - name: present assertions
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_check_mode_present is changed
+ - intf_policy_leaf_polgrp_present is changed
+ - intf_policy_leaf_polgrp_present.previous == []
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.attributes.lagT == 'link'
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.attributes.name == 'policygroupname_link'
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.children.0.infraRsFcIfPol.attributes.tnFcIfPolName == 'fiberchannelpolicy'
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.children.1.infraRsHIfPol.attributes.tnFabricHIfPolName == 'linklevelpolicy'
+ - intf_policy_leaf_polgrp_present.current.0.infraAccBndlGrp.attributes.annotation == 'orchestrator:ansible'
+ - intf_policy_leaf_polgrp_idempotent is not changed
+ - intf_policy_leaf_polgrp_idempotent.sent == {}
+ - intf_policy_leaf_polgrp_update is changed
+ - intf_policy_leaf_polgrp_update.sent.infraAccBndlGrp.attributes.descr == 'policygroup description'
+
+ - 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
+ policy_group: policygroupname_link
+ lag_type: link
+ state: query
+ register: binding_query
+
+ - name: present assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query.current | length >= 1
+ - '"/api/mo/uni/infra/funcprof/accbundle-policygroupname_link.json" in binding_query.url'
+
+ - name: Remove interface policy leaf policy group (PC) - check mode
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_absent
+ check_mode: true
+ register: intf_policy_leaf_polgrp_check_mode_absent
+
+ - name: Remove interface policy leaf policy group (PC) - delete works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_absent
+ register: intf_policy_leaf_polgrp_absent
+
+ - name: Remove interface policy leaf policy group (PC) - idempotency works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_absent
+ register: intf_policy_leaf_polgrp_absent_idempotent
+
+ - 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
+ policy_group: policygroupname_link
+ #lag_type: link
+ state: absent
+ ignore_errors: true
+ register: intf_policy_leaf_polgrp_absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_check_mode_absent is changed
+ - intf_policy_leaf_polgrp_check_mode_absent.previous != []
+ - intf_policy_leaf_polgrp_absent is changed
+ - intf_policy_leaf_polgrp_absent.previous == intf_policy_leaf_polgrp_absent.previous
+ - intf_policy_leaf_polgrp_absent_idempotent is not changed
+ - intf_policy_leaf_polgrp_absent_idempotent.previous == []
+ - intf_policy_leaf_polgrp_absent_missing_param is failed
+ - 'intf_policy_leaf_polgrp_absent_missing_param.msg == "missing required arguments: lag_type"'
+
+ # ==== END TESTING Port Channel (PC), lag_type: link ====
+
+
+ # ==== START TESTING Virtual Port Channel (VPC), lag_type: node ====
+
+ - 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
+
+ - 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
+ policy_group: policygroupname_node
+ lag_type: node
+ link_level_policy: linklevelpolicy
+ fibre_channel_interface_policy: fiberchannelpolicy
+ state: present
+ check_mode: true
+ register: intf_policy_leaf_polgrp_check_mode_present
+
+ - name: Adding a interface policy leaf policy group (VPC) - creation works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_node_present
+ register: intf_policy_leaf_polgrp_present
+
+ - name: Adding a interface policy leaf policy group (VPC) - idempotency works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_node_present
+ register: intf_policy_leaf_polgrp_idempotent
+
+ - name: Adding a interface policy leaf policy group description (VPC) - update works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_node_present
+ description: policygroup description
+ register: intf_policy_leaf_polgrp_update
+
+ # TODO: also test for errors
+ - name: present assertions
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_check_mode_present is changed
+ - intf_policy_leaf_polgrp_present is changed
+ - intf_policy_leaf_polgrp_present.previous == []
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.attributes.lagT == 'node'
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.attributes.name == 'policygroupname_node'
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.children.0.infraRsFcIfPol.attributes.tnFcIfPolName == 'fiberchannelpolicy'
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.children.1.infraRsHIfPol.attributes.tnFabricHIfPolName == 'linklevelpolicy'
+ - intf_policy_leaf_polgrp_present.sent.infraAccBndlGrp.attributes.name == 'policygroupname_node'
+ - intf_policy_leaf_polgrp_idempotent is not changed
+ - intf_policy_leaf_polgrp_idempotent.sent == {}
+ - intf_policy_leaf_polgrp_update is changed
+ - intf_policy_leaf_polgrp_update.sent.infraAccBndlGrp.attributes.descr == 'policygroup description'
+
+ - 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
+ policy_group: policygroupname_node
+ lag_type: node
+ state: query
+ register: binding_query
+
+ - name: present assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query.current | length >= 1
+ - '"/api/mo/uni/infra/funcprof/accbundle-policygroupname_node.json" in binding_query.url'
+
+ # Add lag_type link to see what we get back
+ - name: Adding a interface policy leaf policy group (PC) - creation works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_link_present
+ register: intf_policy_leaf_polgrp_present
+
+ - 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
+ lag_type: node
+ state: query
+ register: binding_query_node_all
+
+ - name: present assertions
+ assert:
+ that:
+ - binding_query_node_all is not changed
+ - binding_query_node_all.current | length >= 1
+ - binding_query_node_all.current | selectattr("infraAccBndlGrp.attributes.lagT", "equalto", "link") | list == []
+ - '"/api/class/infraAccBndlGrp.json" in binding_query_node_all.url'
+
+ - name: Remove interface policy leaf policy group (VPC) - check mode
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_node_absent
+ check_mode: true
+ register: intf_policy_leaf_polgrp_check_mode_absent
+
+ - name: Remove interface policy leaf policy group (VPC) - delete works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_node_absent
+ register: intf_policy_leaf_polgrp_absent
+
+ - name: Remove interface policy leaf policy group (VPC) - idempotency works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *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
+ 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
+ policy_group: policygroupname_node
+ #lag_type: node
+ state: absent
+ ignore_errors: true
+ register: intf_policy_leaf_polgrp_absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_check_mode_absent is changed
+ - intf_policy_leaf_polgrp_check_mode_absent.previous != []
+ - intf_policy_leaf_polgrp_absent is changed
+ - intf_policy_leaf_polgrp_absent.previous == intf_policy_leaf_polgrp_absent.previous
+ - intf_policy_leaf_polgrp_absent_idempotent is not changed
+ - intf_policy_leaf_polgrp_absent_idempotent.previous == []
+ - intf_policy_leaf_polgrp_absent_missing_param is failed
+ - 'intf_policy_leaf_polgrp_absent_missing_param.msg == "missing required arguments: lag_type"'
+
+ # ==== END TESTING Virtual Port Channel (VPC), lag_type: node ====
+
+
+ # ==== START TESTING Virtual Port Channel (VPC), lag_type: leaf ====
+
+ - 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
+
+ - 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
+ policy_group: policygroupname_leaf
+ lag_type: leaf
+ link_level_policy: linklevelpolicy
+ fibre_channel_interface_policy: fiberchannelpolicy
+ state: present
+ check_mode: true
+ register: intf_policy_leaf_polgrp_check_mode_present
+
+ - name: Adding a interface policy leaf policy group (Leaf Access Port) - creation works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ register: intf_policy_leaf_polgrp_present
+
+ - name: Adding a interface policy leaf policy group (Leaf Access Port) - idempotency works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ register: intf_policy_leaf_polgrp_idempotent
+
+ - name: Adding a interface policy leaf policy group description (Leaf Access Port) - update works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ description: policygroup description
+ register: intf_policy_leaf_polgrp_update
+
+ - name: Adding a interface policy leaf policy group (Leaf Access Port) - null parameter works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ port_channel_policy: null
+ ignore_errors: true
+ register: intf_policy_leaf_polgrp_parameter
+
+ - name: Adding a interface policy leaf policy group (Leaf Access Port) - port_channel_policy not supported error
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_present
+ port_channel_policy: "default"
+ ignore_errors: true
+ register: intf_policy_leaf_polgrp_pc_policy_error
+
+ # TODO: also test for errors
+ - name: present assertions
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_check_mode_present is changed
+ - intf_policy_leaf_polgrp_present is changed
+ - intf_policy_leaf_polgrp_present.previous == []
+ - 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_idempotent is not changed
+ - intf_policy_leaf_polgrp_idempotent.sent == {}
+ - intf_policy_leaf_polgrp_update is changed
+ - intf_policy_leaf_polgrp_update.sent.infraAccPortGrp.attributes.descr == 'policygroup description'
+ - intf_policy_leaf_polgrp_parameter is not changed
+ - intf_policy_leaf_polgrp_pc_policy_error.msg == 'port_channel_policy is not a valid parameter for leaf (leaf access port policy group), if used assign null to it (port_channel_policy{{":"}} null).'
+
+ - 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
+ policy_group: policygroupname_leaf
+ lag_type: leaf
+ state: query
+ register: binding_query
+
+ - name: present assertions
+ 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'
+
+ - name: Remove interface policy leaf policy group (Leaf Access Port) - check mode
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_absent
+ check_mode: true
+ register: intf_policy_leaf_polgrp_check_mode_absent
+
+ - name: Remove interface policy leaf policy group (Leaf Access Port) - delete works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *aci_interface_policy_leaf_policy_group_leaf_absent
+ register: intf_policy_leaf_polgrp_absent
+
+ - name: Remove interface policy leaf policy group (Leaf Access Port) - idempotency works
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ <<: *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
+ 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
+ policy_group: policygroupname_leaf
+ #lag_type: leaf
+ state: absent
+ ignore_errors: true
+ register: intf_policy_leaf_polgrp_absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - intf_policy_leaf_polgrp_check_mode_absent is changed
+ - intf_policy_leaf_polgrp_check_mode_absent.previous != []
+ - intf_policy_leaf_polgrp_absent is changed
+ - intf_policy_leaf_polgrp_absent.previous == intf_policy_leaf_polgrp_absent.previous
+ - intf_policy_leaf_polgrp_absent_idempotent is not changed
+ - intf_policy_leaf_polgrp_absent_idempotent.previous == []
+ - intf_policy_leaf_polgrp_absent_missing_param is failed
+ - 'intf_policy_leaf_polgrp_absent_missing_param.msg == "missing required arguments: lag_type"'
+
+ # ==== END TESTING Virtual Port Channel (VPC), lag_type: leaf ====
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_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_interface_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 000000000..51d553c54
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,273 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish <ssrish@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)
+
+- 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
+ block: # block specifies execution of tasks within, based on conditions
+ # CLEAN ENVIRONMENT
+ - name: Remove leaf profile
+ cisco.aci.aci_interface_policy_leaf_profile: &interface_policy_leaf_profile_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") }}'
+ leaf_interface_profile: ansible_test
+ state: absent
+
+ - name: Remove leaf_interface_profile fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_absent
+ type: fex
+ leaf_interface_profile: ansible_test_fex
+
+ # ADD LEAF INTERFACE PROFILE
+ - name: Add leaf interface profile (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile: &interface_policy_leaf_profile_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") }}'
+ interface_profile: ansible_test
+ state: present
+ check_mode: true
+ register: cm_add_leaf_interface_profile
+
+ - name: Add leaf interface profile (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_present
+ register: nm_add_leaf_interface_profile
+
+ - name: Add leaf interface profile again (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_present
+ check_mode: true
+ register: cm_add_leaf_interface_profile_again
+
+ - name: Add leaf interface profile again (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_present
+ register: nm_add_leaf_interface_profile_again
+
+ - name: Add leaf interface profile fex (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_present
+ type: fex
+ leaf_interface_profile: ansible_test_fex
+ register: nm_add_leaf_interface_profile_fex
+
+ - name: Verify add_leaf_interface_profile
+ assert:
+ that:
+ - cm_add_leaf_interface_profile is changed
+ - nm_add_leaf_interface_profile is changed
+ - nm_add_leaf_interface_profile.current.0.infraAccPortP.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_leaf_interface_profile_again is not changed
+ - nm_add_leaf_interface_profile_again is not changed
+ - nm_add_leaf_interface_profile_fex is changed
+
+ # CHANGE LEAF INTERFACE PROFILE
+ - name: Change description of leaf interface profile (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_present
+ description: Ansible test leaf interface profile
+ check_mode: true
+ register: cm_add_leaf_interface_profile_descr
+
+ - name: Change description of leaf interface profile (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_present
+ description: Ansible test leaf interface profile
+ register: nm_add_leaf_interface_profile_descr
+
+ - name: Change description of leaf interface profile again (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_present
+ description: Ansible test leaf interface profile
+ check_mode: true
+ register: cm_add_leaf_interface_profile_descr_again
+
+ - name: Change description of leaf interface profile again (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_present
+ description: Ansible test leaf interface profile
+ register: nm_add_leaf_interface_profile_descr_again
+
+ - name: Change description of leaf interface profile fex (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_present
+ type: fex
+ description: Ansible test leaf interface profile fex
+ leaf_interface_profile: ansible_test_fex
+ register: nm_add_leaf_interface_profile_descr_fex
+
+ - name: Verify add_leaf_interface_profile_descr
+ assert:
+ that:
+ - cm_add_leaf_interface_profile_descr is changed
+ - nm_add_leaf_interface_profile_descr is changed
+ - nm_add_leaf_interface_profile_descr_fex is changed
+ - cm_add_leaf_interface_profile_descr_again is not changed
+ - nm_add_leaf_interface_profile_descr_again is not changed
+
+ # ADD LEAF INTERFACE PROFILE AGAIN
+ - name: Add leaf interface profile again with no description (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_present
+ check_mode: true
+ register: cm_add_leaf_interface_profile_again_no_descr
+
+ - name: Add leaf interface profile again with no description (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_present
+ register: nm_add_leaf_interface_profile_again_no_descr
+
+ - name: Add leaf interface profile again with no description fex (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_present
+ type: fex
+ leaf_interface_profile: ansible_test_fex
+ register: nm_add_leaf_interface_profile_again_no_descr_fex
+
+ - name: Verify add_leaf_interface_profile_again_no_descr
+ assert:
+ that:
+ - cm_add_leaf_interface_profile_again_no_descr is not changed
+ - nm_add_leaf_interface_profile_again_no_descr is not changed
+ - nm_add_leaf_interface_profile_again_no_descr_fex is not changed
+
+ # QUERY ALL LEAF INTERFACE PROFILES
+ - name: Query all interface profiles (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile: &interface_policy_leaf_profile_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_leaf_interface_profiles
+
+ - name: Query all leaf_interface_profiles (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_query
+ register: nm_query_all_leaf_interface_profiles
+
+ - name: Query all fex (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_query
+ type: fex
+
+ - name: Verify query_all_leaf_interface_profiles
+ assert:
+ that:
+ - cm_query_all_leaf_interface_profiles is not changed
+ - nm_query_all_leaf_interface_profiles is not changed
+ # NOTE: Order of leaf_interface_profiles is not stable between calls
+ #- cm_query_all_leaf_interface_profiles == nm_query_all_leaf_interface_profiles
+
+ # QUERY A LEAF INTERFACE PROFILE
+ - name: Query our leaf_interface_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_query
+ leaf_interface_profile: ansible_test
+ check_mode: true
+ register: cm_query_leaf_interface_profile
+
+ - name: Query our leaf_interface_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_query
+ leaf_interface_profile: ansible_test
+ register: nm_query_leaf_interface_profile
+
+ - name: Query our leaf_interface_profile fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_query
+ type: fex
+ leaf_interface_profile: ansible_test_fex
+ register: nm_query_leaf_interface_profile_fex
+
+ - name: Verify query_leaf_interface_profile
+ assert:
+ that:
+ - cm_query_leaf_interface_profile is not changed
+ - nm_query_leaf_interface_profile is not changed
+ - nm_query_leaf_interface_profile_fex is not changed
+ - cm_query_leaf_interface_profile == nm_query_leaf_interface_profile
+
+ # REMOVE LEAF INTERFACE PROFILE
+ - name: Remove leaf_interface_profile (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_absent
+ check_mode: true
+ register: cm_remove_leaf_interface_profile
+
+ - name: Remove leaf_interface_profile (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_absent
+ register: nm_remove_leaf_interface_profile
+
+ - name: Remove leaf_interface_profile again (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_absent
+ check_mode: true
+ register: cm_remove_leaf_interface_profile_again
+
+ - name: Remove leaf_interface_profile again (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile: *interface_policy_leaf_profile_absent
+ register: nm_remove_leaf_interface_profile_again
+
+ - name: Remove leaf_interface_profile fex (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_absent
+ type: fex
+ leaf_interface_profile: ansible_test_fex
+ register: nm_remove_leaf_interface_profile_again_fex
+
+ - name: Verify remove_leaf_interface_profile
+ assert:
+ that:
+ - cm_remove_leaf_interface_profile is changed
+ - nm_remove_leaf_interface_profile is changed
+ - nm_remove_leaf_interface_profile_again_fex is changed
+ - cm_remove_leaf_interface_profile_again is not changed
+ - nm_remove_leaf_interface_profile_again is not changed
+
+ # QUERY NON-EXISTING LEAF INTERFACE PROFILE
+ - name: Query non-existing leaf_interface_profile (check_mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_query
+ leaf_interface_profile: ansible_test
+ check_mode: true
+ register: cm_query_non_leaf_interface_profile
+
+ - name: Query non-existing leaf_interface_profile (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_query
+ leaf_interface_profile: ansible_test
+ register: nm_query_non_leaf_interface_profile
+
+ - name: Query non-existing leaf_interface_profile fex (normal mode)
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *interface_policy_leaf_profile_query
+ type: fex
+ leaf_interface_profile: ansible_test_fex
+ register: nm_query_non_leaf_interface_profile_fex
+
+ # TODO: Implement more tests
+ - name: Verify query_non_leaf_interface_profile
+ assert:
+ that:
+ - cm_query_non_leaf_interface_profile is not changed
+ - nm_query_non_leaf_interface_profile is not changed
+ - nm_query_non_leaf_interface_profile_fex is not changed
+ - cm_query_non_leaf_interface_profile == nm_query_non_leaf_interface_profile \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_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_profile_fex_policy_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml
new file mode 100644
index 000000000..41853af11
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile_fex_policy_group/tasks/main.yml
@@ -0,0 +1,295 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure anstest_fex_profile - Interface Policy Fex profile does not exists
+ cisco.aci.aci_interface_policy_leaf_profile: &fex_profile_absent
+ <<: *aci_info
+ type: fex
+ leaf_interface_profile: anstest_fex_profile
+ state: absent
+
+ - name: Add anstest_fex_profile - Interface Policy Fex profile
+ cisco.aci.aci_interface_policy_leaf_profile: &fex_profile_present
+ <<: *fex_profile_absent
+ state: present
+ register: fex_profile_present
+
+ - name: Add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with check mode
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &cm_fex_policy_group_present
+ <<: *aci_info
+ name: anstest_fex_policy_group
+ fex_profile: anstest_fex_profile
+ state: present
+ check_mode: true
+ register: cm_fex_policy_group_present
+
+ - name: Assertions check for add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with check mode
+ assert:
+ that:
+ - cm_fex_policy_group_present is changed
+ - cm_fex_policy_group_present.current | length == 0
+ - cm_fex_policy_group_present.previous | length == 0
+ - cm_fex_policy_group_present.sent.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - cm_fex_policy_group_present.sent.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+
+ - name: Add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &nm_fex_policy_group_present
+ <<: *cm_fex_policy_group_present
+ register: nm_fex_policy_group_present
+
+ - name: Assertions check for add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode
+ assert:
+ that:
+ - nm_fex_policy_group_present is changed
+ - nm_fex_policy_group_present.current | length == 1
+ - nm_fex_policy_group_present.previous | length == 0
+ - nm_fex_policy_group_present.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - nm_fex_policy_group_present.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+
+ - name: Add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode - idempotency works
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &idempotency_fex_policy_group_present
+ <<: *nm_fex_policy_group_present
+ register: idempotency_fex_policy_group_present
+
+ - name: Idempotency assertions check for add Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode
+ assert:
+ that:
+ - idempotency_fex_policy_group_present is not changed
+ - idempotency_fex_policy_group_present.current | length == 1
+ - idempotency_fex_policy_group_present.previous | length == 1
+ - idempotency_fex_policy_group_present.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - idempotency_fex_policy_group_present.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+ - idempotency_fex_policy_group_present.previous.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - idempotency_fex_policy_group_present.previous.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+
+ - name: Add multiple Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ <<: *aci_info
+ name: "{{ item.name }}"
+ fex_profile: "{{ item.fex_profile }}"
+ state: present
+ with_items:
+ - name: anstest_fex_policy_group_1
+ fex_profile: anstest_fex_profile
+ - name: anstest_fex_policy_group_2
+ fex_profile: anstest_fex_profile
+ register: multiple_fex_policy_group_present
+
+ - name: Assertions check for add multiple Fex Policy Group to anstest_fex_profile - Interface Policy Fex profile with normal mode
+ assert:
+ that:
+ - multiple_fex_policy_group_present is changed
+ - multiple_fex_policy_group_present.results.0 is changed
+ - multiple_fex_policy_group_present.results.1 is changed
+ - multiple_fex_policy_group_present.results.0.current | length == 1
+ - multiple_fex_policy_group_present.results.1.current | length == 1
+ - multiple_fex_policy_group_present.results.0.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group_1"
+ - multiple_fex_policy_group_present.results.1.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group_2"
+ - multiple_fex_policy_group_present.results.0.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group_1"
+ - multiple_fex_policy_group_present.results.1.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group_2"
+
+ - name: Ensure temp_anstest_fex_profile - Interface Policy Fex profile does not exists
+ cisco.aci.aci_interface_policy_leaf_profile: &temp_anstest_fex_profile_absent
+ <<: *aci_info
+ type: fex
+ leaf_interface_profile: temp_anstest_fex_profile
+ state: absent
+ register: temp_anstest_fex_profile_absent
+
+ - name: Assertions check for remove temp_anstest_fex_profile - Interface Policy Fex profile
+ assert:
+ that:
+ - temp_anstest_fex_profile_absent.current | length == 0
+
+ - name: Add temp_anstest_fex_profile - Interface Policy Fex profile
+ cisco.aci.aci_interface_policy_leaf_profile: &temp_anstest_fex_profile_present
+ <<: *temp_anstest_fex_profile_absent
+ state: present
+ register: temp_anstest_fex_profile_present
+
+ - name: Assertions check for add temp_anstest_fex_profile - Interface Policy Fex profile
+ assert:
+ that:
+ - temp_anstest_fex_profile_present is changed
+ - temp_anstest_fex_profile_present.current | length == 1
+ - temp_anstest_fex_profile_present.previous | length == 0
+
+ - name: Add Fex Policy Group to temp_anstest_fex_profile - Interface Policy Fex profile
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ <<: *aci_info
+ name: anstest_fex_policy_group
+ fex_profile: temp_anstest_fex_profile
+ state: present
+ register: temp_anstest_fex_policy_group_present
+
+ - name: Assertions check for add Fex Policy Group to temp_anstest_fex_profile - Interface Policy Fex profile
+ assert:
+ that:
+ - temp_anstest_fex_policy_group_present is changed
+ - temp_anstest_fex_policy_group_present.current | length == 1
+ - temp_anstest_fex_policy_group_present.previous | length == 0
+ - temp_anstest_fex_policy_group_present.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - temp_anstest_fex_policy_group_present.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-temp_anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+
+ - name: Query anstest_fex_policy_group - fex policy group with fex_profile
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ <<: *aci_info
+ name: anstest_fex_policy_group
+ fex_profile: anstest_fex_profile
+ state: query
+ register: query_res_fex_policy_group_with_profile
+
+ - name: Assertions check for query anstest_fex_policy_group - fex policy group with fex_profile
+ assert:
+ that:
+ - query_res_fex_policy_group_with_profile is not changed
+ - query_res_fex_policy_group_with_profile.current | length == 1
+ - query_res_fex_policy_group_with_profile.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - query_res_fex_policy_group_with_profile.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+
+ - name: Query all fex policy group under anstest_fex_profile
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ <<: *aci_info
+ fex_profile: anstest_fex_profile
+ state: query
+ register: query_all_policy_groups_under_fex_profile
+
+ - name: Assertions check for query all fex policy group under anstest_fex_profile
+ assert:
+ that:
+ - query_all_policy_groups_under_fex_profile is not changed
+ - query_all_policy_groups_under_fex_profile.current.0.infraFexP.children | length == 3
+
+ - name: Query all anstest_fex_policy_group - fex policy groups
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ <<: *aci_info
+ name: anstest_fex_policy_group
+ state: query
+ register: query_res_anstest_fex_policy_group
+
+ - name: Assertions check for query all anstest_fex_policy_group - fex policy groups
+ assert:
+ that:
+ - query_res_anstest_fex_policy_group is not changed
+ - query_res_anstest_fex_policy_group.current | length >= 2
+ - query_res_anstest_fex_policy_group.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - query_res_anstest_fex_policy_group.current.1.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+
+ - name: Query all - fex policy groups
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ <<: *aci_info
+ state: query
+ register: all_fex_policy_groups
+
+ - name: Assertions check for query all - fex policy groups
+ assert:
+ that:
+ - all_fex_policy_groups is not changed
+ - all_fex_policy_groups.current | length >= 4
+
+ - name: Remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with check mode
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &cm_anstest_fex_policy_group_absent
+ <<: *aci_info
+ name: anstest_fex_policy_group
+ fex_profile: anstest_fex_profile
+ state: absent
+ check_mode: true
+ register: cm_anstest_fex_policy_group_absent
+
+ - name: Assertions check for remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with check mode
+ assert:
+ that:
+ - cm_anstest_fex_policy_group_absent is changed
+ - cm_anstest_fex_policy_group_absent.current | length == 1
+ - cm_anstest_fex_policy_group_absent.previous | length == 1
+ - cm_anstest_fex_policy_group_absent.current.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - cm_anstest_fex_policy_group_absent.current.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+ - cm_anstest_fex_policy_group_absent.previous.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - cm_anstest_fex_policy_group_absent.previous.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+
+ - name: Remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with normal mode
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &nm_anstest_fex_policy_group_absent
+ <<: *cm_anstest_fex_policy_group_absent
+ register: nm_anstest_fex_policy_group_absent
+
+ - name: Assertions check for remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with normal mode
+ assert:
+ that:
+ - nm_anstest_fex_policy_group_absent is changed
+ - nm_anstest_fex_policy_group_absent.current | length == 0
+ - nm_anstest_fex_policy_group_absent.previous | length == 1
+ - nm_anstest_fex_policy_group_absent.previous.0.infraFexBndlGrp.attributes.name == "anstest_fex_policy_group"
+ - nm_anstest_fex_policy_group_absent.previous.0.infraFexBndlGrp.attributes.dn == "uni/infra/fexprof-anstest_fex_profile/fexbundle-anstest_fex_policy_group"
+
+ - name: Remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with normal mode - idempotency works
+ cisco.aci.aci_interface_policy_leaf_profile_fex_policy_group:
+ &idempotency_anstest_fex_policy_group_absent
+ <<: *nm_anstest_fex_policy_group_absent
+ register: idempotency_anstest_fex_policy_group_absent
+
+ - name: Idempotency assertions check for remove anstest_fex_policy_group - Fex Policy Group from anstest_fex_profile with normal mode
+ assert:
+ that:
+ - idempotency_anstest_fex_policy_group_absent is not changed
+ - idempotency_anstest_fex_policy_group_absent.current | length == 0
+ - idempotency_anstest_fex_policy_group_absent.previous | length == 0
+
+ - name: Remove temp_anstest_fex_profile Fex Profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *temp_anstest_fex_profile_present
+ state: absent
+ register: temp_anstest_fex_profile_absent
+
+ - name: Assertions check for remove temp_anstest_fex_profile Fex Profile
+ assert:
+ that:
+ - temp_anstest_fex_profile_absent is changed
+ - temp_anstest_fex_profile_absent.current | length == 0
+ - temp_anstest_fex_profile_absent.previous | length == 1
+ - temp_anstest_fex_profile_absent.previous.0.infraFexP.attributes.name == "temp_anstest_fex_profile"
+ - temp_anstest_fex_profile_absent.previous.0.infraFexP.attributes.dn == "uni/infra/fexprof-temp_anstest_fex_profile"
+
+ - name: Remove anstest_fex_profile Fex Profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *fex_profile_present
+ state: absent
+ register: fex_profile_present_absent
+
+ - name: Assertions check for remove anstest_fex_profile Fex Profile
+ assert:
+ that:
+ - fex_profile_present_absent is changed
+ - fex_profile_present_absent.current | length == 0
+ - fex_profile_present_absent.previous | length == 1
+ - fex_profile_present_absent.previous.0.infraFexP.attributes.name == "anstest_fex_profile"
+ - fex_profile_present_absent.previous.0.infraFexP.attributes.dn == "uni/infra/fexprof-anstest_fex_profile"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/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_link_level/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml
new file mode 100644
index 000000000..a3ee0c4b8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml
@@ -0,0 +1,292 @@
+# Test code for the ACI modules
+# Copyright: (c) 2019, Vasily Prokopov (@vasilyprokopov)
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# GNU General Public License v3.0+ (see COPYING 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
+ block: # block specifies execution of tasks within, based on conditions
+ # CLEAN ENVIRONMENT
+ - name: Remove Link Level Policy
+ aci_interface_policy_link_level: &interface_policy_link_level_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") }}'
+ link_level_policy: ansible_test
+ state: absent
+
+ # ADD LINK LEVEL POLICY
+ - name: Add Link Level Policy (check mode)
+ aci_interface_policy_link_level: &interface_policy_link_level_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") }}'
+ link_level_policy: ansible_test
+ state: present
+ check_mode: true
+ register: cm_add_policy
+
+ - name: Add Link Level Policy (normal mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_present
+ register: nm_add_policy
+
+ - name: Verify Add Link Level Policy
+ assert:
+ that:
+ - cm_add_policy is changed
+ - nm_add_policy is changed
+ - nm_add_policy.previous == cm_add_policy.previous == cm_add_policy.current == []
+ - nm_add_policy.current.0.fabricHIfPol.attributes.name == 'ansible_test'
+ - nm_add_policy.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'
+ - nm_add_policy.current.0.fabricHIfPol.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_policy.proposed.fabricHIfPol.attributes.name == cm_add_policy.proposed.fabricHIfPol.attributes.name == nm_add_policy.sent.fabricHIfPol.attributes.name == 'ansible_test'
+
+ - name: Add Link Level Policy again (check mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_present
+ check_mode: true
+ register: cm_add_policy_again
+
+ - name: Add Link Level Policy again (normal mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_present
+ register: nm_add_policy_again
+
+ - name: Verify Add Link Level Policy again
+ assert:
+ that:
+ - cm_add_policy_again is not changed
+ - nm_add_policy_again is not changed
+ - nm_add_policy_again.previous.0.fabricHIfPol.attributes.name == cm_add_policy_again.previous.0.fabricHIfPol.attributes.name == nm_add_policy_again.current.0.fabricHIfPol.attributes.name == cm_add_policy_again.current.0.fabricHIfPol.attributes.name == 'ansible_test'
+ - nm_add_policy.proposed.fabricHIfPol.attributes.name == cm_add_policy.proposed.fabricHIfPol.attributes.name == nm_add_policy.sent.fabricHIfPol.attributes.name == cm_add_policy.sent.fabricHIfPol.attributes.name == 'ansible_test'
+ - nm_add_policy_again.sent == cm_add_policy_again.sent == {}
+
+ # CHANGE LINK LEVEL POLICY
+ - name: Change description of Link Level Policy (check mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_present
+ description: Ansible test Link Level Policy
+ check_mode: true
+ register: cm_add_policy_descr
+
+ - name: Change description of Link Level Policy (normal mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_present
+ description: Ansible test Link Level Policy
+ register: nm_add_policy_descr
+
+ - name: Verify add_policy_descr
+ assert:
+ that:
+ - cm_add_policy_descr is changed
+ - nm_add_policy_descr is changed
+ - cm_add_policy_descr.proposed.fabricHIfPol.attributes.name == nm_add_policy_descr.proposed.fabricHIfPol.attributes.name == 'ansible_test'
+ - nm_add_policy_descr.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'
+
+ - name: Change description of Link Level Policy again (check mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_present
+ description: Ansible test Link Level Policy
+ check_mode: true
+ register: cm_add_policy_descr_again
+
+ - name: Change description of Link Level Policy again (normal mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_present
+ description: Ansible test Link Level Policy
+ register: nm_add_policy_descr_again
+
+ - name: Verify add_policy_descr_again
+ assert:
+ that:
+ - cm_add_policy_descr_again is not changed
+ - nm_add_policy_descr_again is not changed
+ - cm_add_policy_descr_again.proposed.fabricHIfPol.attributes.name == nm_add_policy_descr_again.proposed.fabricHIfPol.attributes.name == 'ansible_test'
+ - cm_add_policy_descr_again.sent == nm_add_policy_descr_again.sent == {}
+ - cm_add_policy_descr_again.previous.0.fabricHIfPol.attributes.dn == nm_add_policy_descr_again.previous.0.fabricHIfPol.attributes.dn == cm_add_policy_descr_again.current.0.fabricHIfPol.attributes.dn == nm_add_policy_descr_again.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'
+
+ # ADD LINK LEVEL POLICY AGAIN WITH NO DESCRIPTION
+ - name: Add Link Level Policy again with no description (check mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_present
+ check_mode: true
+ register: cm_add_policy_again_no_descr
+
+ - name: Add Link Level Policy again with no description (normal mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_present
+ register: nm_add_policy_again_no_descr
+
+ - name: Verify add_policy_again_no_descr
+ assert:
+ that:
+ - cm_add_policy_again_no_descr is not changed
+ - nm_add_policy_again_no_descr is not changed
+ - cm_add_policy_again_no_descr.proposed.fabricHIfPol.attributes.name == nm_add_policy_again_no_descr.proposed.fabricHIfPol.attributes.name == 'ansible_test'
+ - cm_add_policy_again_no_descr.sent == nm_add_policy_again_no_descr.sent == {}
+ - cm_add_policy_again_no_descr.previous.0.fabricHIfPol.attributes.dn== nm_add_policy_again_no_descr.previous.0.fabricHIfPol.attributes.dn == cm_add_policy_again_no_descr.current.0.fabricHIfPol.attributes.dn == nm_add_policy_again_no_descr.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'
+
+ # QUERY ALL LINK LEVEL POLICIES
+ - name: Query all Link Level Policies (check mode)
+ aci_interface_policy_link_level: &interface_policy_link_level_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_policies
+
+ - name: Query all Link Level Policies (normal mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_query
+ register: nm_query_all_policies
+
+ - name: Verify query_all_policies
+ assert:
+ that:
+ - cm_query_all_policies is not changed
+ - nm_query_all_policies is not changed
+ - cm_query_all_policies == nm_query_all_policies
+ - nm_query_all_policies.current|length >= 1
+
+ # QUERY A LINK LEVEL POLICY
+ - name: Query our Link Level Policy (check mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_query
+ link_level_policy: ansible_test
+ check_mode: true
+ register: cm_query_policy
+
+ - name: Query our Link Level Policy (normal mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_query
+ link_level_policy: ansible_test
+ register: nm_query_policy
+
+ - name: Verify query_policy
+ assert:
+ that:
+ - cm_query_policy is not changed
+ - nm_query_policy is not changed
+ - cm_query_policy == nm_query_policy
+ - nm_query_policy.current.0.fabricHIfPol.attributes.descr == 'Ansible test Link Level Policy'
+ - nm_query_policy.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'
+ - nm_query_policy.current.0.fabricHIfPol.attributes.name == 'ansible_test'
+
+ # REMOVE LINK LEVEL POLICY
+ - name: Remove Link Level Policy (check mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_absent
+ check_mode: true
+ register: cm_remove_policy
+
+ - name: Remove Link Level Policy (normal mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_absent
+ register: nm_remove_policy
+
+ - name: Verify remove_policy
+ assert:
+ that:
+ - cm_remove_policy is changed
+ - nm_remove_policy is changed
+ - cm_remove_policy.proposed == nm_remove_policy.proposed == {}
+ - cm_remove_policy.sent == nm_remove_policy.sent == {}
+ - cm_remove_policy.previous.0.fabricHIfPol.attributes.dn == nm_remove_policy.previous.0.fabricHIfPol.attributes.dn == cm_remove_policy.current.0.fabricHIfPol.attributes.dn == 'uni/infra/hintfpol-ansible_test'
+ - nm_remove_policy.current == []
+
+ - name: Remove Link Level Policy again (check mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_absent
+ check_mode: true
+ register: cm_remove_policy_again
+
+ - name: Remove Link Level Policy again (normal mode)
+ aci_interface_policy_link_level: *interface_policy_link_level_absent
+ register: nm_remove_policy_again
+
+ - name: Verify remove_policy_again
+ assert:
+ that:
+ - cm_remove_policy_again is not changed
+ - nm_remove_policy_again is not changed
+ - cm_remove_policy_again.proposed == nm_remove_policy_again.proposed == {}
+ - cm_remove_policy_again.sent == nm_remove_policy_again.sent == {}
+ - cm_remove_policy_again.previous == nm_remove_policy_again.previous == cm_remove_policy_again.current == nm_remove_policy_again.current == []
+
+ # QUERY NON-EXISTING LINK LEVEL POLICY
+ - name: Query non-existing Link Level Policy (check mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_query
+ link_level_policy: ansible_test
+ check_mode: true
+ register: cm_query_non_policy
+
+ - name: Query non-existing Link Level Policy (normal mode)
+ aci_interface_policy_link_level:
+ <<: *interface_policy_link_level_query
+ link_level_policy: ansible_test
+ register: nm_query_non_policy
+
+ - name: Verify query_non_policy
+ assert:
+ that:
+ - cm_query_non_policy is not changed
+ - nm_query_non_policy is not changed
+ - cm_query_non_policy == nm_query_non_policy
+ - cm_query_non_policy.current == nm_query_non_policy.current == []
+
+ # PROVOKE ERRORS - REQUIRED PARAMETER MISSING
+ - name: Error when required parameter is missing
+ aci_interface_policy_link_level:
+ 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") }}'
+ state: present
+ ignore_errors: true
+ register: error_on_missing_required_param
+
+ - name: Verify error_on_missing_required_param
+ assert:
+ that:
+ - error_on_missing_required_param is failed
+ - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: link_level_policy"'
+
+ # PROVOKE ERRORS - DEBOUNCE OUT OF RANGE
+ - name: Error when link debounce interval is out of range
+ aci_interface_policy_link_level:
+ 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") }}'
+ state: present
+ link_level_policy: ansible_test
+ link_debounce_interval: 5005
+ ignore_errors: true
+ register: error_on_debounce_out_of_range
+
+ - name: Verify error_on_debounce_out_of_range
+ assert:
+ that:
+ - error_on_debounce_out_of_range is failed
+ - 'error_on_debounce_out_of_range.msg == "The \"link_debounce_interval\" must be a value between 0 and 5000"' \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/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_ospf/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml
new file mode 100644
index 000000000..96a5472f0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml
@@ -0,0 +1,232 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (dagwieers) <dag@wieers.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
+
+
+# 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
+ 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
+ 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
+ state: present
+ check_mode: true
+ register: cm_add_ospf_interface_policy
+
+- name: Add ospf interface policy (normal mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_present
+ register: nm_add_ospf_interface_policy
+
+- name: Add ospf interface policy again (check_mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_present
+ check_mode: true
+ register: cm_add_ospf_interface_policy_again
+
+- name: Add ospf interface policy again (normal mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_present
+ register: nm_add_ospf_interface_policy_again
+
+- name: Verify add_ospf_interface_policy
+ assert:
+ that:
+ - cm_add_ospf_interface_policy is changed
+ - nm_add_ospf_interface_policy is changed
+ - nm_add_ospf_interface_policy.current.0.ospfIfPol.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_ospf_interface_policy_again is not changed
+ - nm_add_ospf_interface_policy_again is not changed
+
+
+# CHANGE OSPF INTERFACE POLICY
+- name: Change description of ospf interface policy (check_mode)
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_present
+ description: Ansible test ospf interface policy
+ 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
+ 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
+ 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
+ register: nm_add_ospf_descr_again
+
+- name: Verify add_ospf_descr
+ assert:
+ that:
+ - cm_add_ospf_descr is changed
+ - nm_add_ospf_descr is changed
+ - cm_add_ospf_descr_again is not changed
+ - nm_add_ospf_descr_again is not changed
+
+
+# ADD OSPF INTERFACE POLICY AGAIN
+- name: Add ospf interface policy again with no description (check_mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_present
+ check_mode: true
+ register: cm_add_ospf_again_no_descr
+
+- name: Add ospf interface policy again with no description (normal mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_present
+ register: nm_add_ospf_again_no_descr
+
+- name: Verify add_ospf_again_no_descr
+ assert:
+ that:
+ - cm_add_ospf_again_no_descr is not changed
+ - nm_add_ospf_again_no_descr is not changed
+
+
+# QUERY ALL OSPF INTERFACE POLICIES
+- name: Query all ospf interface policies (check_mode)
+ cisco.aci.aci_interface_policy_ospf: &interface_policy_ospf_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") }}'
+ tenant: ansible_test
+ state: query
+ check_mode: true
+ register: cm_query_all_ospfs
+
+- name: Query all ospfs (normal mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_query
+ register: nm_query_all_ospfs
+
+- name: Verify query_all_ospfs
+ assert:
+ that:
+ - cm_query_all_ospfs is not changed
+ - nm_query_all_ospfs is not changed
+ # NOTE: Order of ospfs is not stable between calls
+ #- cm_query_all_ospfs == nm_query_all_ospfs
+
+
+# QUERY A OSPF INTERFACE POLICY
+- name: Query our ospf
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_query
+ tenant: ansible_test
+ ospf: ansible_ospf
+ check_mode: true
+ register: cm_query_ospf
+
+- name: Query our ospf
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_query
+ tenant: ansible_test
+ ospf: ansible_ospf
+ register: nm_query_ospf
+
+- name: Verify query_ospf
+ assert:
+ that:
+ - cm_query_ospf is not changed
+ - nm_query_ospf is not changed
+ - cm_query_ospf == nm_query_ospf
+
+
+# REMOVE OSPF INTERFACE POLICY
+- name: Remove ospf (check_mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_absent
+ check_mode: true
+ register: cm_remove_ospf
+
+- name: Remove ospf (normal mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_absent
+ register: nm_remove_ospf
+
+- name: Remove ospf again (check_mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_absent
+ check_mode: true
+ register: cm_remove_ospf_again
+
+- name: Remove ospf again (normal mode)
+ cisco.aci.aci_interface_policy_ospf: *interface_policy_ospf_absent
+ register: nm_remove_ospf_again
+
+- name: Verify remove_ospf
+ assert:
+ that:
+ - cm_remove_ospf is changed
+ - nm_remove_ospf is changed
+ - cm_remove_ospf_again is not changed
+ - nm_remove_ospf_again is not changed
+
+
+# QUERY NON-EXISTING OSPF INTERFACE POLICY
+- name: Query non-existing ospf (check_mode)
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_query
+ ospf: ansible_ospf
+ check_mode: true
+ register: cm_query_non_ospf
+
+- name: Query non-existing ospf (normal mode)
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_query
+ ospf: ansible_ospf
+ register: nm_query_non_ospf
+
+# TODO: Implement more tests
+- name: Verify query_non_ospf
+ assert:
+ that:
+ - cm_query_non_ospf is not changed
+ - nm_query_non_ospf is not changed
+ - cm_query_non_ospf == nm_query_non_ospf
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/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_security/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml
new file mode 100644
index 000000000..c040bfb1e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml
@@ -0,0 +1,177 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish <ssrish@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: Remove policy port security
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: '{{ item }}'
+ state: absent
+ loop:
+ - security1
+ - security2
+ - security3
+
+ # ADD
+ - name: Add a port security interface policy - check mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security1
+ description: security 1
+ max_end_points: 300
+ port_security_timeout: 190
+ state: present
+ check_mode: true
+ register: port_security1_cm
+
+ - name: Add a port security interface policy - normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security1
+ description: security 1
+ max_end_points: 300
+ port_security_timeout: 190
+ state: present
+ register: port_security1_nm
+
+ - name: Add a port security interface policy again - normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security1
+ description: security 1
+ max_end_points: 300
+ port_security_timeout: 190
+ state: present
+ register: port_security1_nm_again
+
+ - name: Add a port security interface policy - normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security2
+ description: security 2
+ max_end_points: 300
+ port_security_timeout: 10
+ state: present
+ ignore_errors: true
+ register: port_security1_nm_error_timeout
+
+ - name: Add a port security interface policy - normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security3
+ description: security 3
+ max_end_points: 15000
+ port_security_timeout: 60
+ state: present
+ ignore_errors: true
+ register: port_security1_nm_error_max
+
+ - name: Add a port security interface policy again for security 3- normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security3
+ description: security 3
+ max_end_points: 12000
+ port_security_timeout: 60
+ state: present
+ ignore_errors: true
+ register: port_security1_nm_with_no_error
+
+ - name: Verify present cases
+ assert:
+ that:
+ - port_security1_cm is changed
+ - port_security1_nm is changed
+ - port_security1_cm.proposed.l2PortSecurityPol.attributes.dn == "uni/infra/portsecurityP-security1"
+ - port_security1_cm.proposed.l2PortSecurityPol.attributes.name == "security1"
+ - port_security1_cm.proposed.l2PortSecurityPol.attributes.timeout == "190"
+ - port_security1_cm.proposed.l2PortSecurityPol.attributes.maximum == "300"
+ - port_security1_cm.proposed.l2PortSecurityPol.attributes.descr == "security 1"
+ - port_security1_nm.current.0.l2PortSecurityPol.attributes.dn == "uni/infra/portsecurityP-security1"
+ - port_security1_nm.current.0.l2PortSecurityPol.attributes.name == "security1"
+ - port_security1_nm.current.0.l2PortSecurityPol.attributes.timeout == "190"
+ - port_security1_nm.current.0.l2PortSecurityPol.attributes.maximum == "300"
+ - port_security1_nm.current.0.l2PortSecurityPol.attributes.descr == "security 1"
+ - port_security1_nm.current.0.l2PortSecurityPol.attributes.annotation == 'orchestrator:ansible'
+ - port_security1_nm_again is not changed
+ - port_security1_nm_error_timeout.msg == "The port_security_timeout must be between 60 and 3600"
+ - port_security1_nm_error_max.msg == "The max_end_points must be between 0 and 12000"
+
+ # QUERY
+ - name: Query a port security interface policy - normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security1
+ state: query
+ register: port_security1_query
+
+ - name: Query all port security interface policies - normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ state: query
+ register: port_all_query
+
+ - name: Verify query cases
+ assert:
+ that:
+ - port_security1_query is not changed
+ - port_all_query is not changed
+ - port_security1_query.current.0.l2PortSecurityPol.attributes.dn == "uni/infra/portsecurityP-security1"
+ - port_security1_query.current.0.l2PortSecurityPol.attributes.name == "security1"
+ - port_security1_query.current.0.l2PortSecurityPol.attributes.timeout == "190"
+ - port_security1_query.current.0.l2PortSecurityPol.attributes.maximum == "300"
+ - port_security1_query.current.0.l2PortSecurityPol.attributes.descr == "security 1"
+ - port_all_query.current|length >= 1
+
+ # REMOVE
+ - name: Remove a port security interface policy - normal mode
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: security1
+ state: absent
+ register: port_security1_remove
+
+ - name: Verify remove cases
+ assert:
+ that:
+ - port_security1_remove is changed
+ - port_security1_remove.previous.0.l2PortSecurityPol.attributes.dn == "uni/infra/portsecurityP-security1"
+ - port_security1_remove.previous.0.l2PortSecurityPol.attributes.name == "security1"
+ - port_security1_remove.previous.0.l2PortSecurityPol.attributes.timeout == "190"
+ - port_security1_remove.previous.0.l2PortSecurityPol.attributes.maximum == "300"
+ - port_security1_remove.previous.0.l2PortSecurityPol.attributes.descr == "security 1"
+
+ # CLEAN END
+ - name: Remove all policy port securities
+ aci_interface_policy_port_security:
+ <<: *aci_info
+ port_security: '{{ item }}'
+ state: absent
+ loop:
+ - security1
+ - security2
+ - security3 \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/aliases
new file mode 100644
index 000000000..cf765b70b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/aliases
@@ -0,0 +1 @@
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml
new file mode 100644
index 000000000..3bb33d896
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_spanning_tree/tasks/main.yml
@@ -0,0 +1,162 @@
+# Test code for the ACI modules
+
+# Copyright: (c) 2023, Eric Girard <@netgirard>
+# 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 execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ # CLEAN ENVIRONMENT
+ - name: Remove policy spanning tree
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: "{{ item }}"
+ state: absent
+ loop:
+ - stp_bpduguard
+ - stp_bpdufilter
+ - stp_both
+
+ # ADD
+ - name: Add a spanning tree interface policy BPDU Guard - check mode
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_bpduguard
+ description: BPDU Guard
+ bpdu_guard: true
+ state: present
+ check_mode: true
+ register: stp_bpduguard_cm
+
+ - name: Add a spanning tree interface policy BPDU Guard - normal mode
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_bpduguard
+ description: BPDU Guard
+ bpdu_guard: true
+ state: present
+ register: stp_bpduguard_nm
+
+ - name: Add a spanning tree interface policy BPDU Guard - normal mode again
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_bpduguard
+ description: BPDU Guard
+ bpdu_guard: true
+ state: present
+ register: stp_bpduguard_nm_again
+
+ - name: Add a spanning tree interface policy BPDU Filter - check mode
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_bpdufilter
+ description: BPDU Filter
+ bpdu_filter: true
+ state: present
+ check_mode: true
+ register: stp_bpdufilter_cm
+
+ - name: Add a spanning tree interface policy BPDU Filter - normal mode
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_bpdufilter
+ description: BPDU Filter
+ bpdu_filter: true
+ state: present
+ register: stp_bpdufilter_nm
+
+ - name: Add a spanning tree interface policy BPDU Filter - normal mode again
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_bpdufilter
+ description: BPDU Filter
+ bpdu_filter: true
+ state: present
+ register: stp_bpdufilter_nm_again
+
+ - name: Add a spanning tree interface policy Both - normal mode
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_both
+ description: Both controls
+ bpdu_guard: true
+ bpdu_filter: true
+ state: present
+ register: stp_both_nm
+
+ - name: Add a spanning tree interface policy Both - normal mode again
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_both
+ description: Both controls
+ bpdu_guard: true
+ bpdu_filter: true
+ state: present
+ register: stp_both_nm_again
+
+ - name: verify add tasks
+ assert:
+ that:
+ - stp_bpduguard_cm is changed
+ - stp_bpduguard_nm is changed
+ - stp_bpduguard_nm_again is not changed
+ - stp_bpdufilter_cm is changed
+ - stp_bpdufilter_nm is changed
+ - stp_bpdufilter_nm_again is not changed
+ - stp_both_nm is changed
+ - stp_both_nm_again is not changed
+ - stp_bpduguard_nm.current.0.stpIfPol.attributes.ctrl == 'bpdu-guard'
+ - stp_bpdufilter_nm.current.0.stpIfPol.attributes.ctrl == 'bpdu-filter'
+ - stp_both_nm.current.0.stpIfPol.attributes.ctrl == 'bpdu-filter,bpdu-guard'
+
+ # QUERY
+ - name: Query a spanning tree interface policy
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: stp_both
+ state: query
+ register: stp_query_both
+
+ - name: Query all spanning tree interface policies
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ state: query
+ register: stp_query_all
+
+ - name: verify query tasks
+ assert:
+ that:
+ - stp_query_both is not changed
+ - stp_query_all is not changed
+ - stp_query_both.current.0.stpIfPol.attributes.ctrl == 'bpdu-filter,bpdu-guard'
+ - stp_query_all.current|length >= 3
+
+ # CLEAN ENVIRONMENT
+ - name: Remove policy port security
+ aci_interface_policy_spanning_tree:
+ <<: *aci_info
+ stp_policy: "{{ item }}"
+ state: absent
+ loop:
+ - stp_bpduguard
+ - stp_bpdufilter
+ - stp_both \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_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_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 000000000..099b2eed9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,181 @@
+# Test code for the ACI modules
+# 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)
+
+- 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
+ block: # block specifies execution of tasks within, based on conditions
+ - name: delete Switch Policy Leaf profile for kick off
+ cisco.aci.aci_switch_policy_leaf_profile:
+ 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") }}'
+ leaf_profile: swleafprftest
+ state: absent
+
+ - name: delete Interface Policy Leaf profile for kick off
+ cisco.aci.aci_interface_policy_leaf_profile:
+ 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") }}'
+ leaf_interface_profile: leafintprftest
+ state: absent
+
+ - name: Ensuring Switch Policy Leaf profile exists for kick off
+ cisco.aci.aci_switch_policy_leaf_profile: &aci_switch_policy_leaf_profile_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
+ leaf_profile: swleafprftest
+ state: present
+ register: leaf_profile_present
+
+ - name: Ensuring Interface Policy Leaf profile exists for kick off
+ cisco.aci.aci_interface_policy_leaf_profile: &aci_interface_policy_leaf_profile_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") }}'
+ leaf_interface_profile: leafintprftest
+ state: present
+ register: leaf_profile_present
+
+ - name: Bind an Interface Selector to a Switch Policy Leaf Profile - check mode works
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile: &aci_interface_selector_to_switch_policy_leaf_profile_present
+ <<: *aci_switch_policy_leaf_profile_present
+ interface_selector: leafintprftest
+ check_mode: true
+ register: intftoleaf_check_mode_present
+
+ - name: Bind an Interface Selector to a Switch Policy Leaf Profile - creation works
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ <<: *aci_interface_selector_to_switch_policy_leaf_profile_present
+ register: intftoleaf_present
+
+ - name: Bind an Interface Selector to a Switch Policy Leaf Profile - idempotency works
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ <<: *aci_interface_selector_to_switch_policy_leaf_profile_present
+ register: intftoleaf_idempotent
+
+ # TODO: also test for errors
+ - name: present assertions
+ assert:
+ that:
+ - intftoleaf_check_mode_present is changed
+ - intftoleaf_present is changed
+ - intftoleaf_present.previous == []
+ - intftoleaf_present.sent.infraRsAccPortP.attributes.tDn == 'uni/infra/accportprof-leafintprftest'
+ - intftoleaf_present.current.0.infraRsAccPortP.attributes.annotation == 'orchestrator:ansible'
+ - intftoleaf_idempotent is not changed
+ - intftoleaf_idempotent.sent == {}
+
+ - name: Query an interface selector profile associated with a switch policy leaf profile
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ interface_selector: leafintprftest
+ state: query
+ register: binding_query1
+
+ - name: query 1 assertions
+ assert:
+ that:
+ - binding_query1 is not changed
+ - binding_query1.current | length >= 1
+ - '"api/mo/uni/infra/nprof-swleafprftest/rsaccPortP-[uni/infra/accportprof-leafintprftest].json" in binding_query1.url'
+
+ - name: Query interface selector profile associations without specifying a switch policy leaf profile
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ 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
+ interface_selector: leafintprftest
+ state: query
+ register: binding_query2
+
+ - name: query 2 assertions
+ assert:
+ that:
+ - binding_query2 is not changed
+ - binding_query2.current | length >= 1
+ - binding_query2.filter_string == '?query-target-filter=eq(infraRsAccPortP.tDn,"uni/infra/accportprof-leafintprftest")'
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile: &aci_interface_selector_to_switch_policy_leaf_profile_absent
+ <<: *aci_switch_policy_leaf_profile_present
+ interface_selector: leafintprftest
+ state: absent
+ check_mode: true
+ register: intftoleaf_check_mode_absent
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - delete works
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ <<: *aci_interface_selector_to_switch_policy_leaf_profile_absent
+ register: intftoleaf_absent
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - idempotency works
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ <<: *aci_interface_selector_to_switch_policy_leaf_profile_absent
+ register: intftoleaf_absent_idempotent
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ state: absent
+ ignore_errors: true
+ register: intftoleaf_absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - intftoleaf_check_mode_absent is changed
+ - intftoleaf_check_mode_absent.previous != []
+ - intftoleaf_absent is changed
+ - intftoleaf_absent.previous == intftoleaf_check_mode_absent.previous
+ - intftoleaf_absent_idempotent is not changed
+ - intftoleaf_absent_idempotent.previous == []
+ - intftoleaf_absent_missing_param is failed
+ - 'intftoleaf_absent_missing_param.msg == "state is absent but all of the following are missing: interface_selector"'
+
+ - name: Remove an interface selector associated with a Switch Policy Leaf Profile - Clean up
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ <<: *aci_interface_selector_to_switch_policy_leaf_profile_absent
+ state: absent
+
+ - name: delete Switch Policy Leaf profile - Clean up
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ state: absent
+
+ - name: delete Interface Policy Leaf profile - Clean up
+ cisco.aci.aci_interface_policy_leaf_profile:
+ <<: *aci_interface_policy_leaf_profile_present
+ leaf_interface_profile: leafintprftest
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml
new file mode 100644
index 000000000..f72831322
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml
@@ -0,0 +1,136 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: Add a new L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ description: Test deployment
+ bd: ansible_bd
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ register: add_l2out
+
+ - name: Verify add_l2out
+ assert:
+ that:
+ - add_l2out.current.0.l2extOut.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out"
+ - add_l2out.current.0.l2extOut.attributes.name == "ansible_l2out"
+ - add_l2out.current.0.l2extOut.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add the L2Out again
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ description: Test deployment
+ bd: ansible_bd
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ register: add_l2out_again
+
+ - name: Verify add_l2out_again
+ assert:
+ that:
+ - add_l2out_again is not changed
+
+ - name: Add a new L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out_2
+ description: Test deployment
+ bd: ansible_bd
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ register: add_l2out_2
+
+ - name: Verify add_l2out_2
+ assert:
+ that:
+ - add_l2out_2.current.0.l2extOut.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out_2"
+ - add_l2out_2.current.0.l2extOut.attributes.name == "ansible_l2out_2"
+
+ - name: Query the L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ state: query
+ register: query_l2out
+
+ - name: Verify query_l2out
+ assert:
+ that:
+ - query_l2out is not changed
+ - query_l2out.current.0.l2extOut.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out"
+ - query_l2out.current.0.l2extOut.attributes.name == "ansible_l2out"
+
+ - name: Query all l2outs under a specific tenant
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: query
+ register: query_l2out_all
+
+ - name: Verify query_l2out_all
+ assert:
+ that:
+ - query_l2out_all is not changed
+
+ - name: Remove the L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ state: absent
+ register: remove_l2out
+
+ - name: Verify remove_l2out
+ assert:
+ that:
+ - remove_l2out is changed
+ - remove_l2out.previous.0.l2extOut.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out"
+ - remove_l2out.previous.0.l2extOut.attributes.name == "ansible_l2out" \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_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_l2out_extepg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml
new file mode 100644
index 000000000..39feb5216
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml
@@ -0,0 +1,163 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: Add New L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ description: Ansible Test
+ bd: ansible_bd
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ register: add_l2out
+
+ - name: Add another L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out_2
+ description: Ansible Test
+ bd: ansible_bd
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ register: add_l2out_2
+
+ - name: Add L2 external end point group
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ description: Ansible external epg
+ preferred_group: True
+ state: present
+ register: l2extepg
+
+ - name: Verify l2extepg
+ assert:
+ that:
+ - l2extepg.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg"
+ - l2extepg.current.0.l2extInstP.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add L2 external end point group again
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ description: Ansible external epg
+ preferred_group: True
+ state: present
+ register: l2extepg_again
+
+ - name: Verify l2extepg_again
+ assert:
+ that:
+ - l2extepg_again is not changed
+ - l2extepg.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg"
+
+ - name: Add another L2 external end point group
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out_2
+ extepg: ansible_extepg_2
+ description: Ansible external epg
+ qos_class: level1
+ preferred_group: True
+ state: present
+ register: l2extepg_2
+
+ - name: Verify l2extepg_2
+ assert:
+ that:
+ - l2extepg_2.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out_2/instP-ansible_extepg_2"
+
+ - name: Query the L2 external end point group
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ state: query
+ register: query_l2extepg
+
+ - name: Query all L2 external epg in a tenant
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: query
+ register: query_all_in_tenant
+
+ - name: Verify query_all_in_tenant
+ assert:
+ that:
+ - query_all_in_tenant is not changed
+
+ - name: Query all L2 external epgs
+ aci_l2out_extepg:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+
+ - name: Remove L2 external end point group
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ preferred_group: True
+ state: absent
+ register: remove_l2extepg
+
+ - name: Verify remove_l2extepg
+ assert:
+ that:
+ - remove_l2extepg is changed
+ - remove_l2extepg.previous.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg" \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml
new file mode 100644
index 000000000..25c211f6b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg_to_contract/tasks/main.yml
@@ -0,0 +1,218 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Anvitha Jain (@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
+
+# 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: Add New L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ description: Ansible Test
+ bd: ansible_bd
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ register: add_l2out
+
+ - name: Add another L2Out
+ aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out_2
+ description: Ansible Test
+ bd: ansible_bd
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ register: add_l2out_2
+
+ - name: Add L2 external end point group
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ description: Ansible external epg
+ preferred_group: True
+ state: present
+ register: l2extepg
+
+ - name: Verify l2extepg
+ assert:
+ that:
+ - l2extepg is changed
+ - l2extepg.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg"
+
+ - name: Add L2 external end point group again
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ description: Ansible external epg
+ preferred_group: True
+ state: present
+ register: l2extepg_again
+
+ - name: Verify l2extepg_again
+ assert:
+ that:
+ - l2extepg_again is not changed
+ - l2extepg.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg"
+
+ - name: Add another L2 external end point group
+ aci_l2out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out_2
+ extepg: ansible_extepg_2
+ description: Ansible external epg
+ qos_class: level1
+ preferred_group: True
+ state: present
+ register: l2extepg_2
+
+ - name: Verify l2extepg_2
+ assert:
+ that:
+ - l2extepg_2 is changed
+ - l2extepg_2.current.0.l2extInstP.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out_2/instP-ansible_extepg_2"
+
+ - name: Bind External End Point Groups to Contracts
+ aci_l2out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ contract: ansible_contract
+ contract_type: provider
+ state: present
+ register: bind_extepg_provider_contract
+
+ - name: Verify bind_extepg_provider_contract
+ assert:
+ that:
+ - bind_extepg_provider_contract is changed
+ - bind_extepg_provider_contract.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg/rsprov-ansible_contract"
+ - bind_extepg_provider_contract.current.0.fvRsProv.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Bind second External End Point Groups to Contracts
+ aci_l2out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out_2
+ extepg: ansible_extepg_2
+ contract: ansible_contract2
+ contract_type: provider
+ state: present
+ register: bind_extepg_provider_contract
+
+ - name: Verify bind_extepg_provider_contract
+ assert:
+ that:
+ - bind_extepg_provider_contract is changed
+ - bind_extepg_provider_contract.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out_2/instP-ansible_extepg_2/rsprov-ansible_contract2"
+
+ - name: Query the External End Point Groups
+ aci_l2out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ contract: ansible_contract
+ contract_type: provider
+ state: query
+ register: query_extepg
+
+ - name: Verify query_extepg
+ assert:
+ that:
+ - query_extepg is not changed
+ - query_extepg.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg/rsprov-ansible_contract"
+
+ - name: Query all the External End Point Groups
+ aci_l2out_extepg_to_contract:
+ <<: *aci_info
+ contract_type: provider
+ state: query
+ register: query_all
+
+ - name: Verify query_extepg
+ assert:
+ that:
+ - query_extepg is not changed
+ - query_extepg.current | length > 0
+
+ - name: Remove existing contract to External End Point Groups
+ aci_l2out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ contract: ansible_contract
+ contract_type: provider
+ state: absent
+ register: remove_contract_extepg
+
+ - name: Verify remove_contract_extepg
+ assert:
+ that:
+ - remove_contract_extepg is changed
+ - remove_contract_extepg.current == []
+ - remove_contract_extepg.previous.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/l2out-ansible_l2out/instP-ansible_extepg/rsprov-ansible_contract"
+
+ - name: Bind External End Point Groups to Contracts
+ aci_l2out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ extepg: ansible_extepg
+ contract: ansible_contract
+ contract_type: consumer
+ provider_match: all
+ state: present
+ ignore_errors: true
+ register: bind_extepg_consumer_contract
+
+ - name: Verify bind_extepg_consumer_contract
+ assert:
+ that:
+ - bind_extepg_consumer_contract is not changed
+ - bind_extepg_consumer_contract.msg == "the 'provider_match' is only configurable for Provided Contracts" \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_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_l2out_logical_interface_path/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml
new file mode 100644
index 000000000..a573668de
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_path/tasks/main.yml
@@ -0,0 +1,202 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Cindy Zhao (@cizhao)
+
+# 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: Remove test tenant before we kickoff
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ tenant: ansible_test
+ 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: 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: Create l2out
+ cisco.aci.aci_l2out:
+ <<: *aci_info
+ tenant: ansible_test
+ l2out: anstest
+ bd: anstest
+ domain: anstest
+ vlan: 3200
+
+ - name: Crete node profile
+ cisco.aci.aci_l2out_logical_node_profile: &np_present
+ <<: *aci_info
+ node_profile: anstest
+ l2out: anstest
+ tenant: ansible_test
+ state: present
+
+ - name: Add interface profile
+ cisco.aci.aci_l2out_logical_interface_profile: &intf_present
+ <<: *np_present
+ interface_profile: INTFS
+
+ - name: Add new path to interface profile (check_mode)
+ cisco.aci.aci_l2out_logical_interface_path: &path_present
+ <<: *aci_info
+ tenant: ansible_test
+ l2out: anstest
+ node_profile: anstest
+ interface_profile: INTFS
+ interface_type: vpc
+ pod_id: 1
+ leaves:
+ - 101
+ - 102
+ interface: '1/7'
+ state: present
+ check_mode: true
+ register: cm_path_to_intfp
+
+ - name: Add new path to interface profile (normal mode)
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_present
+ register: nm_path_to_intfp
+
+ - name: Verify path to interface profile
+ assert:
+ that:
+ - cm_path_to_intfp is changed
+ - nm_path_to_intfp is changed
+ - cm_path_to_intfp.previous == nm_path_to_intfp.previous == []
+ - cm_path_to_intfp.proposed.l2extRsPathL2OutAtt.attributes.dn == 'uni/tn-ansible_test/l2out-anstest/lnodep-anstest/lifp-INTFS/rspathL2OutAtt-[topology/pod-1/protpaths-101-102/pathep-[1/7]]'
+ - nm_path_to_intfp.current.0.l2extRsPathL2OutAtt.attributes.dn == 'uni/tn-ansible_test/l2out-anstest/lnodep-anstest/lifp-INTFS/rspathL2OutAtt-[topology/pod-1/protpaths-101-102/pathep-[1/7]]'
+ - nm_path_to_intfp.current.0.l2extRsPathL2OutAtt.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add another path to interface profile - interface type switch port
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_present
+ interface_type: switch_port
+ leaves: 103
+ interface: anstest
+ state: present
+ register: second_path
+
+ - name: Add third path to interface profile - interface type port channel
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_present
+ interface_type: port_channel
+ leaves: 104
+ interface: anstest2
+ state: present
+ register: third_path
+
+ - name: Verify path to interface profile
+ assert:
+ that:
+ - second_path is changed
+ - third_path is changed
+ - second_path.previous == third_path.previous == []
+ - second_path.current.0.l2extRsPathL2OutAtt.attributes.dn == 'uni/tn-ansible_test/l2out-anstest/lnodep-anstest/lifp-INTFS/rspathL2OutAtt-[topology/pod-1/paths-103/pathep-[ethanstest]]'
+ - third_path.current.0.l2extRsPathL2OutAtt.attributes.dn == 'uni/tn-ansible_test/l2out-anstest/lnodep-anstest/lifp-INTFS/rspathL2OutAtt-[topology/pod-1/paths-104/pathep-[anstest2]]'
+
+ # Add path with incorrect parameter
+ - name: Use vpc interface with one leave
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_present
+ interface_type: vpc
+ leaves: 105
+ interface: test
+ state: present
+ ignore_errors: true
+
+ - name: Use switch_port interface with two leaves
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_present
+ interface_type: switch_port
+ leaves:
+ - 105
+ - 106
+ interface: test
+ state: present
+ ignore_errors: true
+
+ - name: Use more than two leaves
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_present
+ interface_type: switch_port
+ leaves:
+ - 105
+ - 106
+ - 107
+ interface: test
+ state: present
+ ignore_errors: true
+
+ - name: Query all
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *np_present
+ interface_profile: INTFS
+ state: query
+ register: query_all
+
+ - name: Query specific path
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_present
+ state: query
+ register: query_path
+
+ - name: Verify query
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.l2extLIfP.children | length >= 3
+ - query_path is not changed
+ - query_path.current.0.l2extRsPathL2OutAtt.attributes.dn == 'uni/tn-ansible_test/l2out-anstest/lnodep-anstest/lifp-INTFS/rspathL2OutAtt-[topology/pod-1/protpaths-101-102/pathep-[1/7]]'
+
+ - name: Remove path from interface profile (check_mode)
+ cisco.aci.aci_l2out_logical_interface_path: &path_absent
+ <<: *path_present
+ state: absent
+ check_mode: true
+ register: cm_rm_path
+
+ - name: Remove path from interface profile (normal mode)
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_absent
+ register: nm_rm_path
+
+ # Remove non_existing path
+ - name: Remove path again
+ cisco.aci.aci_l2out_logical_interface_path:
+ <<: *path_absent
+ register: rm_non_existing
+
+ - name: Verify remove path
+ assert:
+ that:
+ - cm_rm_path is changed
+ - nm_rm_path is changed
+ - cm_rm_path.proposed == {}
+ - nm_rm_path.current == []
+ - cm_rm_path.previous.0.l2extRsPathL2OutAtt.attributes.dn == nm_rm_path.previous.0.l2extRsPathL2OutAtt.attributes.dn == 'uni/tn-ansible_test/l2out-anstest/lnodep-anstest/lifp-INTFS/rspathL2OutAtt-[topology/pod-1/protpaths-101-102/pathep-[1/7]]'
+ - rm_non_existing is not changed \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_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_l2out_logical_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml
new file mode 100644
index 000000000..7e28c1cd4
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_interface_profile/tasks/main.yml
@@ -0,0 +1,160 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Cindy Zhao (@cizhao)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant before we kickoff
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ tenant: ansible_test
+ 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
+ # SETUP ENVIRONMENT
+ - name: Create tenant
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Create l2out
+ cisco.aci.aci_l2out:
+ <<: *aci_info
+ tenant: ansible_test
+ l2out: l2outintftest
+ bd: l2outintftest
+ domain: l2outintftest
+ vlan: 3200
+
+ - name: Crete node profile
+ cisco.aci.aci_l2out_logical_node_profile: &np_present
+ <<: *aci_info
+ node_profile: l2outintftest
+ l2out: l2outintftest
+ tenant: ansible_test
+ state: present
+
+ # BEGIN WITH TESTS (ADD PROFILE)
+ - name: Add interface profile (check_mode)
+ cisco.aci.aci_l2out_logical_interface_profile: &intf_present
+ <<: *np_present
+ interface_profile: INTFS
+ check_mode: true
+ register: cm_add_intf
+
+ - name: Add interface profile (normal_mode)
+ cisco.aci.aci_l2out_logical_interface_profile:
+ <<: *intf_present
+ register: nm_add_intf
+
+ - name: Verify nm_add_intf
+ assert:
+ that:
+ - cm_add_intf is changed
+ - nm_add_intf is changed
+ - cm_add_intf.previous == nm_add_intf.previous == []
+ - cm_add_intf.sent.l2extLIfP.attributes.name == nm_add_intf.sent.l2extLIfP.attributes.name == 'INTFS'
+ - nm_add_intf.current.0.l2extLIfP.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add profile again, check if idempotency works
+ cisco.aci.aci_l2out_logical_interface_profile:
+ <<: *intf_present
+ register: add_intf_again
+
+ - name: Verify add_intf_again
+ assert:
+ that:
+ - add_intf_again is not changed
+
+ # ADD ANOTHER PROFILE
+ - name: Add another profile
+ cisco.aci.aci_l2out_logical_interface_profile:
+ <<: *intf_present
+ interface_profile: INTF2
+
+ # QUERY ALL PROFILES
+ - name: Query all profiles
+ cisco.aci.aci_l2out_logical_interface_profile:
+ <<: *aci_info
+ state: query
+ l2out: l2outintftest
+ tenant: ansible_test
+ node_profile: l2outintftest
+ register: query_all_profiles
+
+ - name: Verify query_all_profiles
+ assert:
+ that:
+ - query_all_profiles is not changed
+ - query_all_profiles.current.0.l2extLNodeP.children | length > 1
+
+ # QUERY A SPECIFIC PROFILE
+ - name: Query a specific profile
+ cisco.aci.aci_l2out_logical_interface_profile:
+ <<: *intf_present
+ state: query
+ register: query_spec_profile
+
+ - name: Verify query_spec_profile
+ assert:
+ that:
+ - query_spec_profile is not changed
+ - query_spec_profile.current|length == 1
+ - query_spec_profile.current.0.l2extLIfP.attributes.name == 'INTFS'
+ - query_spec_profile.current.0.l2extLIfP.attributes.dn == 'uni/tn-ansible_test/l2out-l2outintftest/lnodep-l2outintftest/lifp-INTFS'
+
+ # QUERY A NON EXISTING PROFILE
+ - name: Query a nonexisting profile
+ cisco.aci.aci_l2out_logical_interface_profile:
+ <<: *np_present
+ interface_profile: nonexist
+ state: query
+ register: query_nonexist_profile
+
+ - name: Verify query_nonexist_profile
+ assert:
+ that:
+ - query_nonexist_profile is not changed
+ - query_nonexist_profile.current == []
+
+ # REMOVE PROFILE
+ - name: Remove interface profile
+ cisco.aci.aci_l2out_logical_interface_profile: &intf_absent
+ <<: *intf_present
+ state: absent
+ register: remove_profile
+
+ - name: Verify remove_profile
+ assert:
+ that:
+ - remove_profile is changed
+ - remove_profile.current == []
+
+ # REMOVE NONEXISTING PROFILE
+ - name: Remove interface profile again (nonexisting)
+ cisco.aci.aci_l2out_logical_interface_profile:
+ <<: *intf_absent
+ register: remove_nonexist_profile
+
+ - name: Verify remove_nonexist_profile
+ assert:
+ that:
+ - remove_nonexist_profile is not changed
+ - remove_nonexist_profile.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_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_l2out_logical_node_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml
new file mode 100644
index 000000000..82b4aaac5
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_logical_node_profile/tasks/main.yml
@@ -0,0 +1,190 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Cindy Zhao (@cizhao)
+
+# 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_info
+ state: present
+ tenant: ansible_tenant
+ register: tenant_present
+
+ - name: Create L2out for tests
+ cisco.aci.aci_l2out:
+ <<: *aci_info
+ state: present
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ bd: ansible_bd
+ domain: ansible_dom
+ vlan: 3200
+ register: l2out_present
+
+ - name: Add L2out node profile (check mode)
+ cisco.aci.aci_l2out_logical_node_profile: &aci_node_profile_present
+ <<: *aci_info
+ node_profile: ansible_node_profile
+ l2out: ansible_l2out
+ tenant: ansible_tenant
+ state: present
+ check_mode: true
+ register: cm_add_node_profile
+
+ - name: Add L2out node profile (normal mode)
+ cisco.aci.aci_l2out_logical_node_profile: *aci_node_profile_present
+ register: nm_add_node_profile
+
+ - name: Add another L2out node profile (normal mode)
+ cisco.aci.aci_l2out_logical_node_profile:
+ <<: *aci_info
+ node_profile: ansible_node_profile2
+ l2out: ansible_l2out
+ tenant: ansible_tenant
+ state: present
+ register: nm_add_second_node_profile
+
+ - name: Verify add_node_profile
+ assert:
+ that:
+ - cm_add_node_profile is changed
+ - nm_add_node_profile is changed
+ - nm_add_second_node_profile is changed
+ - cm_add_node_profile.sent.l2extLNodeP.attributes.name == nm_add_node_profile.sent.l2extLNodeP.attributes.name == 'ansible_node_profile'
+ - cm_add_node_profile.proposed.l2extLNodeP.attributes.name == nm_add_node_profile.proposed.l2extLNodeP.attributes.name == 'ansible_node_profile'
+ - cm_add_node_profile.current == cm_add_node_profile.previous == nm_add_node_profile.previous == []
+ - nm_add_node_profile.current.0.l2extLNodeP.attributes.dn == 'uni/tn-ansible_tenant/l2out-ansible_l2out/lnodep-ansible_node_profile'
+ - nm_add_node_profile.current.0.l2extLNodeP.attributes.name == 'ansible_node_profile'
+ - nm_add_node_profile.current.0.l2extLNodeP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_second_node_profile.current.0.l2extLNodeP.attributes.dn == 'uni/tn-ansible_tenant/l2out-ansible_l2out/lnodep-ansible_node_profile2'
+ - nm_add_second_node_profile.current.0.l2extLNodeP.attributes.name == 'ansible_node_profile2'
+
+ - name: Query existing node profile (check mode)
+ cisco.aci.aci_l2out_logical_node_profile: &query_existing_node_profile
+ <<: *aci_info
+ node_profile: ansible_node_profile
+ l2out: ansible_l2out
+ tenant: ansible_tenant
+ state: query
+ check_mode: true
+ register: cm_query_node_profile
+
+ - name: Query existing node profile (normal mode)
+ cisco.aci.aci_l2out_logical_node_profile: *query_existing_node_profile
+ register: nm_query_node_profile
+
+ - name: Query non-existent node profile
+ cisco.aci.aci_l2out_logical_node_profile:
+ <<: *aci_info
+ node_profile: ansible_fake_node_profile
+ l2out: ansible_l2out
+ tenant: ansible_tenant
+ state: query
+ check_mode: true
+ register: nm_query_fake_node_profile
+
+ - name: Query all node profile for L2out
+ cisco.aci.aci_l2out_logical_node_profile:
+ <<: *aci_info
+ l2out: ansible_l2out
+ tenant: ansible_tenant
+ state: query
+ register: nm_query_all_node_profiles
+
+ - name: Verify query_node_profile
+ assert:
+ that:
+ - cm_query_node_profile is not changed
+ - nm_query_node_profile is not changed
+ - nm_query_fake_node_profile is not changed
+ - nm_query_all_node_profiles is not changed
+ - cm_query_node_profile.current.0.l2extLNodeP.attributes.name == 'ansible_node_profile'
+ - nm_query_node_profile.current.0.l2extLNodeP.attributes.name == 'ansible_node_profile'
+ - nm_query_fake_node_profile.current == []
+ - nm_query_all_node_profiles.current.0.l2extOut.children.0.l2extLNodeP.attributes.name == 'ansible_node_profile2'
+ - nm_query_all_node_profiles.current.0.l2extOut.children.1.l2extLNodeP.attributes.name == 'ansible_node_profile'
+
+ - name: Remove node profile (check mode)
+ cisco.aci.aci_l2out_logical_node_profile: &aci_node_profile_absent
+ <<: *aci_info
+ node_profile: ansible_node_profile
+ l2out: ansible_l2out
+ tenant: ansible_tenant
+ state: absent
+ check_mode: true
+ register: cm_remove_node_profile
+
+ - name: Remove node profile (normal mode)
+ cisco.aci.aci_l2out_logical_node_profile: *aci_node_profile_absent
+ register: nm_remove_node_profile
+
+ - name: Remove node profile (normal mode) again
+ cisco.aci.aci_l2out_logical_node_profile: *aci_node_profile_absent
+ register: nm_remove_node_profile_again
+
+ - name: Remove second node profile (check mode)
+ cisco.aci.aci_l2out_logical_node_profile: &aci_second_node_profile_absent
+ <<: *aci_info
+ node_profile: ansible_node_profile2
+ l2out: ansible_l2out
+ tenant: ansible_tenant
+ state: absent
+ check_mode: true
+ register: cm_remove_second_node_profile
+
+ - name: Remove second node profile (normal mode)
+ cisco.aci.aci_l2out_logical_node_profile: *aci_second_node_profile_absent
+ register: nm_remove_second_node_profile
+
+ - name: Verify remove_node_profile
+ assert:
+ that:
+ - cm_remove_node_profile is changed
+ - cm_remove_second_node_profile is changed
+ - nm_remove_node_profile is changed
+ - nm_remove_node_profile_again is not changed
+ - nm_remove_second_node_profile is changed
+
+ # Remove L2out after testing
+ - name: Remove L2out (normal_mode)
+ cisco.aci.aci_l2out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l2out: ansible_l2out
+ state: absent
+
+ # Remove Tenant after testing
+ - name: Remove tenant (normal_mode)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/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_peer/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml
new file mode 100644
index 000000000..4e1784a6a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_bgp_peer/tasks/main.yml
@@ -0,0 +1,1516 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_tenant if it already exists
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+- name: Remove ansible_l3ext_domain if it already exists
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: absent
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will skip execution for cloud sites
+ block:
+ - name: Remove ansible_port_channel_ipg if it already exists
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: absent
+
+ - name: Remove ansible_vpc_ipg if it already exists
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: absent
+
+ - name: Add a new tenant required for l3out
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ # ADD domain
+ - name: Add domain for l3out
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: present
+
+ # ADD VRF
+ - name: Add VRF for l3out
+ aci_vrf:
+ <<: *aci_info
+ tenant: ansible_tenant
+ vrf: ansible_vrf
+ state: present
+
+ # ADD PC IPG
+ - name: Add port-channel IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: present
+
+ # ADD vPC IPG
+ - name: Add vPC IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: present
+
+ # ADD l3out
+ - name: Add l3out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ vrf: ansible_vrf
+ domain: ansible_domain
+ route_control: export
+ state: present
+
+ # ADD l3out logical node profile
+ - name: l3out logical node profile
+ aci_l3out_logical_node_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ state: present
+
+ # ADD l3out logical interface profile
+ - name: l3out logical interface profile
+ aci_l3out_logical_interface_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ state: present
+
+ # ADD l3out interface
+ - name: Add routed interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.50.1/27
+ state: present
+
+ # ADD l3out port-channel
+ - name: Add routed interface port-channel
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.70.1/27
+ state: present
+
+ # ADD l3out vPC
+ - name: Add interface vPC
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ interface_type: ext-svi
+ mode: native
+ addr: 192.168.90.1/27
+ encap: vlan-913
+ state: present
+
+ # ADD BGP peer to ethernet port
+ - name: add BGP peer to ethernet port (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ address_type_controls:
+ - af-ucast
+ ttl: 2
+ state: present
+ register: add_eth_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: add BGP peer to ethernet port (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ ttl: 2
+ state: present
+ register: add_eth_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been created with correct attributes (version >= 4)
+ assert:
+ that:
+ - add_eth_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - add_eth_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_eth_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-ucast"
+ - add_eth_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "enabled"
+ - add_eth_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - 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'
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been created with correct attributes (version < 4)
+ assert:
+ that:
+ - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "2"
+ - add_eth_bgp_peer_32.current.0.bgpPeerP.attributes.annotation == 'orchestrator:ansible'
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify remote AS object has been created correctly
+ assert:
+ that:
+ - add_eth_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been created correctly
+ assert:
+ that:
+ - add_eth_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # ADD BGP peer again to check idempotence
+ - name: add BGP peer to ethernet port again (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ address_type_controls:
+ - af-ucast
+ ttl: 2
+ state: present
+ register: add_eth_bgp_peer_again
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: add BGP peer to ethernet port again (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ ttl: 2
+ state: present
+ register: add_eth_bgp_peer_again_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been created with correct attributes (version >= 4)
+ assert:
+ that:
+ - add_eth_bgp_peer_again is not changed
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.addrTCtrl == "af-ucast"
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.adminSt == "enabled"
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_eth_bgp_peer_again.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been created with correct attributes (version < 4)
+ assert:
+ that:
+ - add_eth_bgp_peer_again_32 is not changed
+ - add_eth_bgp_peer_again_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - add_eth_bgp_peer_again_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_eth_bgp_peer_again_32.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_eth_bgp_peer_again_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_eth_bgp_peer_again_32.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - 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"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object his still correct (version < 4)
+ assert:
+ that:
+ - add_eth_bgp_peer_again_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # MODIFY BGP peer
+ - name: update BGP peer (version >= 4)
+ aci_l3out_bgp_peer: &interface_profile_bgp_peer_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ remote_asn: 65457
+ bgp_controls:
+ - allow-self-as
+ - as-override
+ peer_controls:
+ - dis-conn-check
+ private_asn_controls:
+ - remove-exclusive
+ address_type_controls:
+ - af-ucast
+ - af-mcast
+ weight: 50
+ allow_self_as_count: 3
+ ttl: 4
+ admin_state: disabled
+ state: present
+ register: update_eth_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: update BGP peer (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ remote_asn: 65457
+ bgp_controls:
+ - allow-self-as
+ - as-override
+ peer_controls:
+ - dis-conn-check
+ private_asn_controls:
+ - remove-exclusive
+ weight: 50
+ allow_self_as_count: 3
+ ttl: 4
+ state: present
+ register: update_eth_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been updated with correct attributes (version >= 4)
+ assert:
+ that:
+ - update_eth_bgp_peer is changed
+ - update_eth_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - update_eth_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - update_eth_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-mcast,af-ucast"
+ - update_eth_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "disabled"
+ - update_eth_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - update_eth_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "dis-conn-check"
+ - 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"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been updated with correct attributes (version < 4)
+ assert:
+ that:
+ - update_eth_bgp_peer_32 is changed
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "dis-conn-check"
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "4"
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.attributes.privateASctrl == "remove-exclusive"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - 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"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been updated correctly (version < 4)
+ assert:
+ that:
+ - update_eth_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # QUERY BGP peer
+ - name: query BGP peer (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ state: query
+ register: query_eth_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: query BGP peer (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ state: query
+ register: query_eth_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer attributes (version >= 4)
+ assert:
+ that:
+ - query_eth_bgp_peer is not changed
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-mcast,af-ucast"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "disabled"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "dis-conn-check"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.ttl == "4"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - query_eth_bgp_peer.current.0.bgpPeerP.attributes.privateASctrl == "remove-exclusive"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer attributes (version < 4)
+ assert:
+ that:
+ - query_eth_bgp_peer_32 is not changed
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "dis-conn-check"
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "4"
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.attributes.privateASctrl == "remove-exclusive"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP remote AS (version >= 4)
+ assert:
+ that:
+ - query_eth_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP remote AS (version < 4)
+ assert:
+ that:
+ - query_eth_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: Execute tasks only for the APIC version version >= 4
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+ block:
+ # Route Control Profile validation check for Interface Profile level
+ - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - check mode
+ aci_l3out_bgp_peer:
+ <<: *interface_profile_bgp_peer_present
+ route_control_profiles:
+ - tenant: "ansible_tenant"
+ profile: "anstest_import"
+ direction: "import"
+ - tenant: "ansible_tenant"
+ profile: "anstest_export"
+ direction: "export"
+ l3out: "anstest_l3out"
+ state: present
+ check_mode: true
+ register: cm_if_rtctrl_present
+
+ - name: Assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - check mode
+ assert:
+ that:
+ - cm_if_rtctrl_present is changed
+ - cm_if_rtctrl_present.sent.bgpPeerP.children | length == 2
+
+ - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - missing param
+ aci_l3out_bgp_peer:
+ <<: *interface_profile_bgp_peer_present
+ route_control_profiles:
+ - tenant: "ansible_tenant"
+ profile: "anstest_import"
+ - tenant: "ansible_tenant"
+ profile: "anstest_export"
+ direction: "export"
+ l3out: "anstest_l3out"
+ state: present
+ register: nm_if_rtctrl_present_missing_param
+ ignore_errors: true
+
+ - name: Assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - missing param
+ assert:
+ that:
+ - nm_if_rtctrl_present_missing_param is failed
+ - "nm_if_rtctrl_present_missing_param.msg == 'missing required arguments: direction found in route_control_profiles'"
+
+ - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode
+ aci_l3out_bgp_peer: &nm_if_rtctrl_present
+ <<: *interface_profile_bgp_peer_present
+ route_control_profiles:
+ - tenant: "ansible_tenant"
+ profile: "anstest_import"
+ direction: "import"
+ - tenant: "ansible_tenant"
+ profile: "anstest_export"
+ direction: "export"
+ l3out: "anstest_l3out"
+ state: present
+ register: nm_if_rtctrl_present
+
+ - name: Assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode
+ assert:
+ that:
+ - nm_if_rtctrl_present is changed
+ - nm_if_rtctrl_present.current | length == 1
+ - nm_if_rtctrl_present.previous | length == 1
+ - nm_if_rtctrl_present.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - nm_if_rtctrl_present.previous.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - nm_if_rtctrl_present.current.0.bgpPeerP.children | length >= nm_if_rtctrl_present.previous.0.bgpPeerP.children | length
+
+ - name: Add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode - idempotency works
+ aci_l3out_bgp_peer:
+ <<: *nm_if_rtctrl_present
+ state: present
+ register: idempotency_nm_if_rtctrl_present
+
+ - name: Idempotency assertions check for add Route Control Profile to the ansible_interface_profile (version >= 4) - normal mode
+ assert:
+ that:
+ - idempotency_nm_if_rtctrl_present is not changed
+ - idempotency_nm_if_rtctrl_present.current | length == 1
+ - idempotency_nm_if_rtctrl_present.previous | length == 1
+ - idempotency_nm_if_rtctrl_present.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - idempotency_nm_if_rtctrl_present.previous.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - idempotency_nm_if_rtctrl_present.current.0.bgpPeerP.children | length >= 2
+ - idempotency_nm_if_rtctrl_present.previous.0.bgpPeerP.children | length >= 2
+
+ - name: Query a BGP Peer with Interface Profile
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ state: query
+ register: query_if_bgp_peer
+
+ - name: Assertions check for query a BGP Peer with Interface Profile
+ assert:
+ that:
+ - query_if_bgp_peer is not changed
+ - query_if_bgp_peer.current | length == 1
+ - query_if_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - query_if_bgp_peer.current.0.bgpPeerP.children | length >= 2
+
+ # Route Control Profile validation check for Node Profile level
+ - name: Add BGP Peer to the Node Profile level (version >= 4) - check mode
+ aci_l3out_bgp_peer: &cm_ln_rtctrl_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ peer_ip: 192.168.50.3
+ route_control_profiles:
+ - tenant: "ansible_tenant"
+ profile: "anstest_import"
+ direction: "import"
+ - tenant: "ansible_tenant"
+ profile: "anstest_export"
+ direction: "export"
+ l3out: "anstest_l3out"
+ state: present
+ check_mode: true
+ register: cm_ln_rtctrl_present
+
+ - name: Assertions check for add BGP Peer to the Node Profile level (version >= 4) - check mode
+ assert:
+ that:
+ - cm_ln_rtctrl_present is changed
+ - cm_ln_rtctrl_present.current | length == 0
+ - cm_ln_rtctrl_present.previous | length == 0
+ - cm_ln_rtctrl_present.sent.bgpPeerP.attributes.addr == "192.168.50.3"
+ - cm_ln_rtctrl_present.sent.bgpPeerP.children | length >= 2
+
+ - name: Add BGP Peer to the Node Profile level (version >= 4) - normal mode
+ aci_l3out_bgp_peer:
+ <<: *cm_ln_rtctrl_present
+ state: present
+ register: nm_ln_rtctrl_present
+
+ - name: Assertions check for add BGP Peer to the Node Profile level (version >= 4) - normal mode
+ assert:
+ that:
+ - nm_ln_rtctrl_present is changed
+ - nm_ln_rtctrl_present.current | length == 1
+ - 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
+
+ - name: Add BGP Peer to the Node Profile level (version >= 4) - normal mode - idempotency works
+ aci_l3out_bgp_peer:
+ <<: *cm_ln_rtctrl_present
+ state: present
+ register: idempotency_nm_ln_rtctrl_present
+
+ - name: Idempotency assertions check for add BGP Peer to the Node Profile level (version >= 4) - normal mode
+ assert:
+ that:
+ - idempotency_nm_ln_rtctrl_present is not changed
+ - idempotency_nm_ln_rtctrl_present.current | length == 1
+ - idempotency_nm_ln_rtctrl_present.current.0.bgpPeerP.attributes.addr == "192.168.50.3"
+ - idempotency_nm_ln_rtctrl_present.current.0.bgpPeerP.children | length >= 2
+ - idempotency_nm_ln_rtctrl_present.previous | length == 1
+ - idempotency_nm_ln_rtctrl_present.previous.0.bgpPeerP.attributes.addr == "192.168.50.3"
+
+ - name: Add BGP Peer to the Node Profile level (version >= 4) - normal mode - missing param
+ aci_l3out_bgp_peer:
+ <<: *cm_ln_rtctrl_present
+ route_control_profiles:
+ - tenant: "ansible_tenant"
+ profile: "anstest_import"
+ - tenant: "ansible_tenant"
+ profile: "anstest_export"
+ direction: "export"
+ l3out: "anstest_l3out"
+ state: present
+ register: nm_ln_rtctrl_present_missing_param
+ ignore_errors: true
+
+ - name: Assertions check for add BGP Peer to the Node Profile level (version >= 4) - normal mode - missing param
+ assert:
+ that:
+ - nm_ln_rtctrl_present_missing_param is failed
+ - "nm_ln_rtctrl_present_missing_param.msg == 'missing required arguments: direction found in route_control_profiles'"
+
+ - name: Query a BGP Peer from the Node Profile level
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ peer_ip: 192.168.50.3
+ state: query
+ register: query_ln_bgp_peer
+
+ - name: Assertions check for query a BGP Peer from the Node Profile level
+ assert:
+ that:
+ - query_ln_bgp_peer is not changed
+ - query_ln_bgp_peer.current | length == 1
+ - query_ln_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.3"
+
+ - name: Query all BGP peers
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ state: query
+ register: query_all_bgp_peer
+
+ - name: Assertions check for query all BGP peers
+ assert:
+ that:
+ - query_all_bgp_peer is not changed
+ - query_all_bgp_peer.current | length != 0
+
+ # DELETE BGP peer
+ - name: delete BGP peer
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ peer_ip: 192.168.50.2
+ state: absent
+ register: remove_eth_bgp_peer
+
+ - name: verify remove_eth_bgp_peer
+ assert:
+ that:
+ - remove_eth_bgp_peer is changed
+ - remove_eth_bgp_peer.current == []
+ - remove_eth_bgp_peer.previous.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/peerP-[192.168.50.2]"
+ - remove_eth_bgp_peer.previous.0.bgpPeerP.attributes.addr == "192.168.50.2"
+
+ # ADD BGP peer to port-channel
+ - name: add BGP peer to port-channel (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ address_type_controls:
+ - af-ucast
+ ttl: 2
+ state: present
+ register: add_pc_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: add BGP peer to port-channel (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ ttl: 2
+ state: present
+ register: add_pc_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been created with correct attributes (version >= 4)
+ assert:
+ that:
+ - add_pc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - add_pc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_pc_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-ucast"
+ - add_pc_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "enabled"
+ - add_pc_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_pc_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_pc_bgp_peer.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been created with correct attributes (version < 4)
+ assert:
+ that:
+ - add_pc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - add_pc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_pc_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_pc_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_pc_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify remote AS object has been created correctly (version >= 4)
+ assert:
+ that:
+ - add_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been created correctly (version < 4)
+ assert:
+ that:
+ - add_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # ADD BGP peer again to check idempotence
+ - name: add BGP peer to port-channel again (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ address_type_controls:
+ - af-ucast
+ ttl: 2
+ state: present
+ register: add_pc_bgp_peer_again
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: add BGP peer to port-channel again (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ ttl: 2
+ state: present
+ register: add_pc_bgp_peer_again_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been created with correct attributes (version >= 4)
+ assert:
+ that:
+ - add_pc_bgp_peer_again is not changed
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.addrTCtrl == "af-ucast"
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.adminSt == "enabled"
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been created with correct attributes (version < 4)
+ assert:
+ that:
+ - add_pc_bgp_peer_again_32 is not changed
+ - add_pc_bgp_peer_again_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - add_pc_bgp_peer_again_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_pc_bgp_peer_again_32.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_pc_bgp_peer_again_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_pc_bgp_peer_again_32.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify remote AS object has been created correctly (version >= 4)
+ assert:
+ that:
+ - add_pc_bgp_peer_again.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been created correctly (version < 4)
+ assert:
+ that:
+ - add_pc_bgp_peer_again_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # MODIFY BGP peer
+ - name: update BGP peer (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65457
+ bgp_controls:
+ - allow-self-as
+ - as-override
+ peer_controls:
+ - bfd
+ - dis-conn-check
+ private_asn_controls:
+ - remove-all
+ - remove-exclusive
+ - replace-as
+ address_type_controls:
+ - af-ucast
+ - af-mcast
+ weight: 50
+ allow_self_as_count: 3
+ ttl: 4
+ admin_state: disabled
+ state: present
+ register: update_pc_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: update BGP peer (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65457
+ bgp_controls:
+ - allow-self-as
+ - as-override
+ peer_controls:
+ - bfd
+ - dis-conn-check
+ private_asn_controls:
+ - remove-all
+ - remove-exclusive
+ - replace-as
+ weight: 50
+ allow_self_as_count: 3
+ ttl: 4
+ state: present
+ register: update_pc_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been updated with correct attributes (version >= 4)
+ assert:
+ that:
+ - update_pc_bgp_peer is changed
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-mcast,af-ucast"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "disabled"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.ttl == "4"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - update_pc_bgp_peer.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been updated with correct attributes (version < 4)
+ assert:
+ that:
+ - update_pc_bgp_peer_32 is changed
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "4"
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify remote AS object has been created correctly (version >= 4)
+ assert:
+ that:
+ - update_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been created correctly (version < 4)
+ assert:
+ that:
+ - update_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # QUERY BGP peer
+ - name: query BGP peer (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ state: query
+ register: query_pc_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: query BGP peer (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ state: query
+ register: query_pc_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer attributes (version >= 4)
+ assert:
+ that:
+ - query_pc_bgp_peer is not changed
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-mcast,af-ucast"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "disabled"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.ttl == "4"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - query_pc_bgp_peer.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer attributes (version < 4)
+ assert:
+ that:
+ - query_pc_bgp_peer_32 is not changed
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "4"
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP remote AS (version >= 4)
+ assert:
+ that:
+ - query_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP remote AS (version < 4)
+ assert:
+ that:
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # DELETE BGP peer
+ - name: delete BGP peer
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ peer_ip: 192.168.50.2
+ state: absent
+ register: remove_pc_bgp_peer
+
+ - name: verify remove_pc_bgp_peer
+ assert:
+ that:
+ - remove_pc_bgp_peer is changed
+ - remove_pc_bgp_peer.current == []
+ - remove_pc_bgp_peer.previous.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/peerP-[192.168.50.2]"
+ - remove_pc_bgp_peer.previous.0.bgpPeerP.attributes.addr == "192.168.50.2"
+
+ # ADD BGP peer to vPC
+ - name: add BGP peer to vPC (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ address_type_controls:
+ - af-ucast
+ ttl: 2
+ state: present
+ register: add_vpc_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: add BGP peer to vPC (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ ttl: 2
+ state: present
+ register: add_vpc_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been created with correct attributes (version >= 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-ucast"
+ - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "enabled"
+ - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_vpc_bgp_peer.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been created with correct attributes (version < 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - add_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify remote AS object has been created correctly (version >= 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been created correctly (version < 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # ADD BGP peer again to check idempotence
+ - name: add BGP peer to vPC again (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ address_type_controls:
+ - af-ucast
+ ttl: 2
+ state: present
+ register: add_vpc_bgp_peer_again
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: add BGP peer to vPC again (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65456
+ bgp_controls:
+ - nh-self
+ - send-com
+ - send-ext-com
+ peer_controls:
+ - bfd
+ ttl: 2
+ state: present
+ register: add_vpc_bgp_peer_again_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been created with correct attributes (version >= 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer_again is not changed
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.addrTCtrl == "af-ucast"
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.adminSt == "enabled"
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been created with correct attributes (version < 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer_again_32 is not changed
+ - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.attributes.ctrl == "nh-self,send-com,send-ext-com"
+ - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd"
+ - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.attributes.ttl == "2"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify remote AS object has been created correctly (version >= 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer_again.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been created correctly (version < 4)
+ assert:
+ that:
+ - add_vpc_bgp_peer_again_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65456"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # MODIFY BGP peer
+ - name: update BGP peer (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65457
+ bgp_controls:
+ - allow-self-as
+ - as-override
+ peer_controls:
+ - bfd
+ - dis-conn-check
+ private_asn_controls:
+ - remove-all
+ - remove-exclusive
+ - replace-as
+ address_type_controls:
+ - af-ucast
+ - af-mcast
+ weight: 50
+ allow_self_as_count: 3
+ ttl: 4
+ admin_state: disabled
+ state: present
+ register: update_vpc_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: update BGP peer (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ remote_asn: 65457
+ bgp_controls:
+ - allow-self-as
+ - as-override
+ peer_controls:
+ - bfd
+ - dis-conn-check
+ private_asn_controls:
+ - remove-all
+ - remove-exclusive
+ - replace-as
+ weight: 50
+ allow_self_as_count: 3
+ ttl: 4
+ state: present
+ register: update_vpc_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer has been updated with correct attributes (version >= 4)
+ assert:
+ that:
+ - update_vpc_bgp_peer is changed
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-mcast,af-ucast"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "disabled"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.ttl == "4"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - update_vpc_bgp_peer.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer has been updated with correct attributes (version < 4)
+ assert:
+ that:
+ - update_vpc_bgp_peer_32 is changed
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "4"
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify remote AS object has been created correctly (version >= 4)
+ assert:
+ that:
+ - update_vpc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify remote AS object has been created correctly (version < 4)
+ assert:
+ that:
+ - update_vpc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # QUERY BGP peer
+ - name: query BGP peer (version >= 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ state: query
+ register: query_vpc_bgp_peer
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: query BGP peer (version < 4)
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ state: query
+ register: query_vpc_bgp_peer_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP peer attributes (version >= 4)
+ assert:
+ that:
+ - query_vpc_bgp_peer is not changed
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.addrTCtrl == "af-mcast,af-ucast"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.adminSt == "disabled"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.ttl == "4"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - query_vpc_bgp_peer.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP peer attributes (version < 4)
+ assert:
+ that:
+ - query_vpc_bgp_peer_32 is not changed
+ - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.addr == "192.168.50.2"
+ - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.ctrl == "allow-self-as,as-override"
+ - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.peerCtrl == "bfd,dis-conn-check"
+ - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.ttl == "4"
+ - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.allowedSelfAsCnt == "3"
+ - query_vpc_bgp_peer_32.current.0.bgpPeerP.attributes.privateASctrl == "remove-all,remove-exclusive,replace-as"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ - name: verify BGP remote AS (version >= 4)
+ assert:
+ that:
+ - query_pc_bgp_peer.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+ - name: verify BGP remote AS (version < 4)
+ assert:
+ that:
+ - query_pc_bgp_peer_32.current.0.bgpPeerP.children.1.bgpAsP.attributes.asn == "65457"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+ # DELETE BGP peer
+ - name: delete BGP peer
+ aci_l3out_bgp_peer:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ peer_ip: 192.168.50.2
+ state: absent
+ register: remove_vpc_bgp_peer
+
+ - name: verify remove_vpc_bgp_peer
+ assert:
+ that:
+ - remove_vpc_bgp_peer is changed
+ - remove_vpc_bgp_peer.current == []
+ - remove_vpc_bgp_peer.previous.0.bgpPeerP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]/peerP-[192.168.50.2]"
+ - remove_vpc_bgp_peer.previous.0.bgpPeerP.attributes.addr == "192.168.50.2"
+
+ # CLEAN UP
+ - name: Remove ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+ - name: Remove ansible_l3ext_domain
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: absent
+
+ - name: Remove ansible_port_channel_ipg
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: absent
+
+ - name: Remove ansible_vpc_ipg
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/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_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml
new file mode 100644
index 000000000..c49475d0a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml
@@ -0,0 +1,152 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: Add a new l3out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ description: l3out for Ansible tenant
+ domain: ansible_dom
+ route_control: export
+ vrf: ansible_vrf
+ l3protocol: ospf
+ state: present
+
+ - name: Add a new ExtEpg
+ aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ name: ansible_extEpg
+ description: ExtEpg for Ansible l3out
+ state: present
+
+ - name: Bind External End Point Groups to Contracts
+ aci_l3out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ contract: ansible_contract
+ contract_type: provider
+ state: present
+ register: bind_extepg_provider_contract
+
+ - name: Verify bind_extepg_provider_contract
+ assert:
+ that:
+ - bind_extepg_provider_contract.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract"
+ - bind_extepg_provider_contract.current.0.fvRsProv.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Bind second External End Point Groups to Contracts
+ aci_l3out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ contract: ansible_contract2
+ contract_type: provider
+ state: present
+ register: bind_extepg_provider_contract_2
+
+ - name: Verify bind_extepg_provider_contract_2
+ assert:
+ that:
+ - bind_extepg_provider_contract_2.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract2"
+
+ - name: Query the External End Point Groups
+ aci_l3out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ contract: ansible_contract
+ contract_type: provider
+ state: query
+ register: query_extepg
+
+ - name: Verify query_extepg
+ assert:
+ that:
+ - query_extepg is not changed
+ - query_extepg.current.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract"
+
+ - name: Query all the External End Point Groups
+ aci_l3out_extepg_to_contract:
+ <<: *aci_info
+ contract_type: provider
+ state: query
+ register: query_all
+
+ - name: Remove existing contract to External End Point Groups
+ aci_l3out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ contract: ansible_contract
+ contract_type: provider
+ state: absent
+ register: remove_contract_extepg
+
+ - name: Verify remove_contract_extepg
+ assert:
+ that:
+ - remove_contract_extepg.previous.0.fvRsProv.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/instP-ansible_extEpg/rsprov-ansible_contract"
+
+ - name: Bind External End Point Groups to Contracts
+ aci_l3out_extepg_to_contract:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ contract: ansible_contract
+ contract_type: consumer
+ provider_match: all
+ state: present
+ ignore_errors: true
+ register: bind_extepg_consumer_contract
+
+ - name: Verify bind_extepg_consumer_contract
+ assert:
+ that:
+ - bind_extepg_consumer_contract.msg == "the 'provider_match' is only configurable for Provided Contracts" \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/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_extsubnet/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml
new file mode 100644
index 000000000..4be8a65f7
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml
@@ -0,0 +1,318 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Cindy Zhao (@cizhao)
+
+# 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: Add a new l3out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ description: l3out for Ansible tenant
+ domain: ansible_dom
+ route_control: export
+ vrf: ansible_vrf
+ l3protocol: ospf
+ state: present
+
+ - name: Add a new ExtEpg
+ aci_l3out_extepg:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ name: ansible_extEpg
+ description: ExtEpg for Ansible l3out
+ state: present
+
+ - name: Add a subnet (check mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ subnet_name: test
+ network: 192.0.2.0/24
+ state: present
+ check_mode: true
+ register: cm_add_subnet
+
+ - name: Add a subnet (normal mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ subnet_name: test
+ network: 192.0.2.0/24
+ state: present
+ register: nm_add_subnet
+
+ - name: Verify cm_add_subnet and nm_add_subnet
+ assert:
+ that:
+ - cm_add_subnet is changed
+ - nm_add_subnet is changed
+ - cm_add_subnet.proposed.l3extSubnet.attributes.ip == "192.0.2.0/24"
+ - cm_add_subnet.proposed.l3extSubnet.attributes.name == "test"
+ - nm_add_subnet.current.0.l3extSubnet.attributes.ip == "192.0.2.0/24"
+ - nm_add_subnet.current.0.l3extSubnet.attributes.name == "test"
+ - nm_add_subnet.current.0.l3extSubnet.attributes.scope == "import-security"
+ - nm_add_subnet.current.0.l3extSubnet.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add subnet again
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ subnet_name: test
+ network: 192.0.2.0/24
+ state: present
+ register: nm_add_subnet_again
+
+ - name: Verify nm_add_subnet_again
+ assert:
+ that:
+ - nm_add_subnet_again is not changed
+
+ - name: Change subnet (check_mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 192.0.2.0/24
+ subnet_name: ansible_test
+ description: description for subnet
+ scope: [ shared-security, import-security ]
+ state: present
+ check_mode: true
+ register: cm_change_subnet
+
+ - name: Change subnet (normal mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 192.0.2.0/24
+ subnet_name: ansible_test
+ description: description for subnet
+ scope: [ shared-security, import-security ]
+ state: present
+ register: nm_change_subnet
+
+ - name: Verify cm_change_subnet and nm_change_subnet
+ assert:
+ that:
+ - cm_change_subnet is changed
+ - nm_change_subnet is changed
+ - cm_change_subnet.previous.0.l3extSubnet.attributes.descr == nm_change_subnet.previous.0.l3extSubnet.attributes.descr == ""
+ - cm_change_subnet.previous.0.l3extSubnet.attributes.name == nm_change_subnet.previous.0.l3extSubnet.attributes.name == "test"
+ - cm_change_subnet.previous.0.l3extSubnet.attributes.scope == nm_change_subnet.previous.0.l3extSubnet.attributes.scope == "import-security"
+ - cm_change_subnet.proposed.l3extSubnet.attributes.descr == "description for subnet"
+ - cm_change_subnet.proposed.l3extSubnet.attributes.name == "ansible_test"
+ - cm_change_subnet.proposed.l3extSubnet.attributes.scope == "import-security,shared-security"
+ - nm_change_subnet.current.0.l3extSubnet.attributes.descr == "description for subnet"
+ - nm_change_subnet.current.0.l3extSubnet.attributes.name == "ansible_test"
+ - nm_change_subnet.current.0.l3extSubnet.attributes.scope == "import-security,shared-security"
+
+ - name: Add another subnet (normal mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 192.1.2.0/24
+ state: present
+ register: nm_add_another_subnet
+
+ - name: Verify nm_add_another_subnet
+ assert:
+ that:
+ - nm_add_another_subnet is changed
+ - nm_add_another_subnet.current.0.l3extSubnet.attributes.ip == "192.1.2.0/24"
+
+ - name: Query all subnets
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ state: query
+ register: query_all
+
+ - name: Query specific subnet
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 192.0.2.0/24
+ state: query
+ register: query_subnet
+
+ - name: Verify query_all and query_subnet
+ assert:
+ that:
+ - query_all is not changed
+ - query_subnet is not changed
+ - query_all.current.0.l3extInstP.children | length == 2
+ - query_subnet.current.0.l3extSubnet.attributes.name == "ansible_test"
+ - query_subnet.current.0.l3extSubnet.attributes.ip == "192.0.2.0/24"
+
+ - name: Remove subnet
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 192.0.2.0/24
+ state: absent
+ register: rm_subnet
+
+ - name: Verify rm_subnet
+ assert:
+ that:
+ - rm_subnet is changed
+ - rm_subnet.current == []
+ - rm_subnet.previous.0.l3extSubnet.attributes.ip == "192.0.2.0/24"
+ - rm_subnet.previous.0.l3extSubnet.attributes.name == "ansible_test"
+
+ - name: Change subnet aggregate mismatch without scope (normal mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 0.0.0.0/0
+ subnet_name: ansible_test
+ description: description for subnet
+ aggregate: [ export-rtctrl, import-rtctrl ]
+ state: present
+ register: nm_aggregate_scope_none
+ ignore_errors: true
+
+ - name: asserts failed aggregate creation tasks
+ assert:
+ that:
+ - nm_aggregate_scope_none is failed
+ - nm_aggregate_scope_none.msg.startswith("missing parameter(s) required by 'aggregate'")
+
+ - name: Change subnet aggregate mismatch (normal mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 0.0.0.0/0
+ subnet_name: ansible_test
+ description: description for subnet
+ scope: [ import-security ]
+ aggregate: [ export-rtctrl, import-rtctrl ]
+ state: present
+ register: nm_aggregate_scope_mismatch
+ ignore_errors: true
+
+ - name: asserts failed aggregate creation tasks
+ assert:
+ that:
+ - nm_aggregate_scope_mismatch is failed
+ - nm_aggregate_scope_mismatch.msg == "All aggregate values ['export-rtctrl', 'import-rtctrl'] need to be defined in scope ['import-security']."
+
+ - name: Change subnet aggregate match (check mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 0.0.0.0/0
+ subnet_name: ansible_test
+ description: description for subnet
+ scope: [ export-rtctrl, import-rtctrl, import-security ]
+ aggregate: [ export-rtctrl, import-rtctrl ]
+ state: present
+ check_mode: true
+ register: cm_aggregate_scope_match
+
+ - name: Change subnet aggregate match (normal mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 0.0.0.0/0
+ subnet_name: ansible_test
+ description: description for subnet
+ scope: [ export-rtctrl, import-rtctrl, import-security ]
+ aggregate: [ export-rtctrl, import-rtctrl ]
+ state: present
+ register: nm_aggregate_scope_match
+
+ - name: asserts success aggregate creation task
+ assert:
+ that:
+ - cm_aggregate_scope_match is changed
+ - cm_aggregate_scope_match.proposed.l3extSubnet.attributes.ip == "0.0.0.0/0"
+ - cm_aggregate_scope_match.proposed.l3extSubnet.attributes.name == "ansible_test"
+ - cm_aggregate_scope_match.proposed.l3extSubnet.attributes.scope == "export-rtctrl,import-rtctrl,import-security"
+ - cm_aggregate_scope_match.proposed.l3extSubnet.attributes.aggregate == "export-rtctrl,import-rtctrl"
+ - nm_aggregate_scope_match.current.0.l3extSubnet.attributes.ip == "0.0.0.0/0"
+ - nm_aggregate_scope_match.current.0.l3extSubnet.attributes.name == "ansible_test"
+ - nm_aggregate_scope_match.current.0.l3extSubnet.attributes.scope == "export-rtctrl,import-rtctrl,import-security"
+ - nm_aggregate_scope_match.current.0.l3extSubnet.attributes.aggregate == "export-rtctrl,import-rtctrl"
+
+ - name: Change subnet other aggregate order (normal mode)
+ cisco.aci.aci_l3out_extsubnet:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ network: 0.0.0.0/0
+ subnet_name: ansible_test
+ description: description for subnet
+ scope: [ export-rtctrl, import-rtctrl, import-security ]
+ aggregate: [ import-rtctrl, export-rtctrl ]
+ state: present
+ register: nm_aggregate_scope_match
+
+ - name: asserts success aggregate creation task reversed input order
+ assert:
+ that:
+ - nm_aggregate_scope_match is not changed \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/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_interface/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml
new file mode 100644
index 000000000..5b2a247d8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface/tasks/main.yml
@@ -0,0 +1,535 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_tenant if it already exists
+ 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: Remove ansible_l3ext_domain if it already exists
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: absent
+
+ - name: Remove ansible_port_channel_ipg if it already exists
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: absent
+
+ - name: Remove ansible_vpc_ipg if it already exists
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: absent
+
+ - name: Add a new tenant required for l3out
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ description: Ansible tenant
+ state: present
+
+ # ADD domain
+ - name: Add domain for l3out
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: present
+
+ # ADD VRF
+ - name: Add VRF for l3out
+ aci_vrf:
+ <<: *aci_info
+ tenant: ansible_tenant
+ vrf: ansible_vrf
+ state: present
+
+ # ADD PC IPG
+ - name: Add port-channel IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: present
+
+ # ADD vPC IPG
+ - name: Add vPC IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: present
+
+ # ADD l3out
+ - name: Add l3out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ vrf: ansible_vrf
+ domain: ansible_domain
+ route_control: export
+ state: present
+
+ # ADD l3out logical node profile
+ - name: l3out logical node profile
+ aci_l3out_logical_node_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ state: present
+
+ # ADD l3out logical interface profile
+ - name: l3out logical interface profile
+ aci_l3out_logical_interface_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ state: present
+
+ # ADD l3out interface
+ - name: Add routed interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.50.1/27
+ ipv6_dad: disabled
+ mtu: 1500
+ auto_state: disabled
+ state: present
+ register: add_l3out_interface
+
+ - name: Verify l3out has been created with the correct attributes
+ assert:
+ that:
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]"
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.50.1/27"
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.ipv6Dad == "disabled"
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.mtu == "1500"
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.autostate == "disabled"
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port"
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+ - add_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.annotation == 'orchestrator:ansible'
+
+ # ADD l3out interface again to check idempotency
+ - name: Add routed interface again
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.50.1/27
+ ipv6_dad: disabled
+ mtu: 1500
+ auto_state: disabled
+ state: present
+ register: add_l3out_interface_again
+
+ - name: Verify l3out has not changed
+ assert:
+ that:
+ - add_l3out_interface_again is not changed
+
+ # MODIFY l3out attributes
+ - name: Update routed interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ interface_type: sub-interface
+ mode: regular
+ addr: 192.168.60.1/27
+ encap: vlan-913
+ state: present
+ register: update_l3out_interface
+
+ - name: Verify routed interface has correct attributes
+ assert:
+ that:
+ - update_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]"
+ - update_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.60.1/27"
+ - update_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "sub-interface"
+ - update_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.encap == "vlan-913"
+ - update_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ # QUERY l3out interface
+ - name: Query routed interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ state: query
+ register: query_l3out_interface
+
+ - name: Verify query_l3out_interface
+ assert:
+ that:
+ - query_l3out_interface is not changed
+ - query_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]"
+ - query_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.60.1/27"
+ - query_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "sub-interface"
+ - query_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.encap == "vlan-913"
+ - query_l3out_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ - name: Query all interfaces
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ state: query
+ register: query_l3out_interfaces
+
+ - name: Verify query_l3out_interfaces
+ assert:
+ that:
+ - query_l3out_interfaces is not changed
+ - query_l3out_interfaces.current.0.l3extLIfP.children.0.l3extRsPathL3OutAtt.attributes.rn == "rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]"
+ - query_l3out_interfaces.current.0.l3extLIfP.children.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.60.1/27"
+ - query_l3out_interfaces.current.0.l3extLIfP.children.0.l3extRsPathL3OutAtt.attributes.ifInstT == "sub-interface"
+ - query_l3out_interfaces.current.0.l3extLIfP.children.0.l3extRsPathL3OutAtt.attributes.encap == "vlan-913"
+ - query_l3out_interfaces.current.0.l3extLIfP.children.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ # DELETE l3out interface
+ - name: Remove routed sub-interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ state: absent
+ register: delete_l3out_interface
+
+ - name: Verify interface has been deleted
+ assert:
+ that:
+ - delete_l3out_interface.current == []
+ - delete_l3out_interface.previous.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]"
+
+ # ADD l3out port-channel
+ - name: Add routed interface port-channel
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.70.1/27
+ state: present
+ register: add_l3out_pc_interface
+
+ - name: Verify l3out port-channel has been created with the correct attributes
+ assert:
+ that:
+ - add_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]"
+ - add_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.70.1/27"
+ - add_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port"
+ - add_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ # ADD l3out port-channel again to check idempotency
+ - name: Add routed interface port-channel again
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.70.1/27
+ state: present
+ register: add_l3out_pc_interface_again
+
+ - name: Verify interface has not changed
+ assert:
+ that:
+ - add_l3out_pc_interface_again is not changed
+
+ # MODIFY l3out port-channel attributes
+ - name: Update routed port-channel interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.80.1/27
+ state: present
+ register: update_l3out_pc_interface
+
+ - name: Verify l3out port-channel has been updated with the correct attributes
+ assert:
+ that:
+ - update_l3out_pc_interface is changed
+ - update_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]"
+ - update_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.80.1/27"
+ - update_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port"
+ - update_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ # QUERY l3out port-channel interface
+ - name: Query l3out port-channel
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ state: query
+ register: query_l3out_pc_interface
+
+ - name: Verify query_l3out_pc_interface
+ assert:
+ that:
+ - query_l3out_pc_interface is not changed
+ - query_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]"
+ - query_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.80.1/27"
+ - query_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "l3-port"
+ - query_l3out_pc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ # DELETE l3out port-channel interface
+ - name: Remove port-channel
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ state: absent
+ register: delete_l3out_pc_interface
+
+ - name: Verify interface has been deleted
+ assert:
+ that:
+ - delete_l3out_pc_interface.current == []
+ - delete_l3out_pc_interface.previous.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]"
+
+ # ADD l3out vPC
+ - name: Add interface vPC
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ interface_type: ext-svi
+ mode: native
+ addr: 192.168.90.1/27
+ encap: vlan-913
+ state: present
+ register: add_l3out_vpc_interface
+
+ - name: Verify l3out vPC has been created with the correct attributes
+ assert:
+ that:
+ - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]"
+ - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/27"
+ - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "ext-svi"
+ - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.encap == "vlan-913"
+ - add_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "native"
+
+ - name: Add interface vPC again
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ interface_type: ext-svi
+ mode: native
+ addr: 192.168.90.1/27
+ encap: vlan-913
+ state: present
+ register: add_l3out_vpc_interface_again
+
+ - name: Verify vPC interface is not changed
+ assert:
+ that:
+ - add_l3out_vpc_interface_again is not changed
+
+ # MODIFY vPC interface
+ - name: Update interface vPC
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ interface_type: ext-svi
+ mode: regular
+ addr: 192.168.90.1/27
+ encap: vlan-913
+ state: present
+ register: modify_l3out_vpc_interface
+
+ - name: Verify l3out vPC has been updated with the correct attributes
+ assert:
+ that:
+ - modify_l3out_vpc_interface is changed
+ - modify_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]"
+ - modify_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/27"
+ - modify_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "ext-svi"
+ - modify_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.encap == "vlan-913"
+ - modify_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ # QUERY vPC interface
+ - name: Query vPC interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ state: query
+ register: query_l3out_vpc_interface
+
+ - name: Verify l3out vPC query
+ assert:
+ that:
+ - query_l3out_vpc_interface is not changed
+ - query_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/protpaths-201-202/pathep-[ansible_vpc_ipg]]"
+ - query_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.addr == "192.168.90.1/27"
+ - query_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.ifInstT == "ext-svi"
+ - query_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.encap == "vlan-913"
+ - query_l3out_vpc_interface.current.0.l3extRsPathL3OutAtt.attributes.mode == "regular"
+
+ - name: Delete vPC interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ state: absent
+ register: delete_l3out_vpc_interface
+
+ - name: Verify vPC interface is deleted
+ assert:
+ that:
+ - delete_l3out_vpc_interface.current == []
+
+ # CLEAN UP
+ - name: Remove ansible_tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
+
+ - name: Remove ansible_l3ext_domain
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: absent
+
+ - name: Remove ansible_port_channel_ipg
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: absent
+
+ - name: Remove ansible_vpc_ipg
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/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_interface_secondary_ip/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml
new file mode 100644
index 000000000..775d40ee8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_interface_secondary_ip/tasks/main.yml
@@ -0,0 +1,502 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant if it already exists
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ 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: Remove port-channel IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: absent
+
+ - name: Remove vPC IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: absent
+
+ # ADD PC IPG
+ - name: Add port-channel IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: present
+
+ # ADD vPC IPG
+ - name: Add vPC IPG
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: present
+
+ # ADD domain
+ - name: Add domain for l3out
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: present
+
+ # ADD tenant
+ - name: Add a new tenant required for l3out
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ description: Ansible tenant
+ state: present
+
+ # ADD VRF
+ - name: Add VRF for l3out
+ aci_vrf:
+ <<: *aci_info
+ tenant: ansible_test
+ vrf: ansible_vrf
+ state: present
+
+ # ADD l3out
+ - name: Add l3out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_test
+ name: ansible_l3out
+ vrf: ansible_vrf
+ domain: ansible_domain
+ route_control: export
+ state: present
+
+ # ADD l3out logical node profile
+ - name: l3out logical node profile
+ aci_l3out_logical_node_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ state: present
+
+ # ADD l3out logical interface profile
+ - name: l3out logical interface profile
+ aci_l3out_logical_interface_profile:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ state: present
+
+ # ADD l3out routed interface
+ - name: Add routed interface
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.50.1/27
+ state: present
+
+ # ADD l3out routed interface po
+ - name: Add routed interface port-channel
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ interface_type: l3-port
+ mode: regular
+ addr: 192.168.70.1/27
+ state: present
+
+ # ADD l3out routed interface vPC
+ - name: Add routed interface vPC
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ interface_type: ext-svi
+ mode: native
+ encap: vlan-913
+ state: present
+
+ # ADD l3out routed interface vPC member
+ - name: Add routed interface vPC member
+ aci_l3out_logical_interface_vpc_member:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ side: A
+ addr: 192.168.90.1/27
+ state: present
+
+ # ADD secondary IPs to the interfaces
+ - name: Add secondary IP to routed interface
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ addr: 192.168.50.2/27
+ ipv6_dad: disabled
+ state: present
+ register: secondary_intf
+
+ - name: Add secondary to IP routed interface port-channel
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ addr: 192.168.70.2/27
+ ipv6_dad: disabled
+ state: present
+ register: secondary_po
+
+ - name: Add secondary IP to routed interface vPC
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ side: A
+ addr: 192.168.90.2/27
+ ipv6_dad: disabled
+ state: present
+ register: secondary_vpc
+
+ - name: Verify secondaries have been created with the correct attributes
+ assert:
+ that:
+ - secondary_intf.current.0.l3extIp.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/addr-[192.168.50.2/27]"
+ - secondary_intf.current.0.l3extIp.attributes.ipv6Dad == "disabled"
+ - secondary_intf.current.0.l3extIp.attributes.annotation == 'orchestrator:ansible'
+ - secondary_po.current.0.l3extIp.attributes.dn== "uni/tn-ansible_test/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/addr-[192.168.70.2/27]"
+ - secondary_po.current.0.l3extIp.attributes.ipv6Dad == "disabled"
+ - secondary_vpc.current.0.l3extIp.attributes.addr == "192.168.90.2/27"
+ - secondary_vpc.current.0.l3extIp.attributes.ipv6Dad == "disabled"
+
+ # CHECK idempotency
+ - name: Add secondary IP to routed interface with no changes
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ addr: 192.168.50.2/27
+ ipv6_dad: disabled
+ state: present
+ register: secondary_intf_again
+
+ - name: Add secondary to IP routed interface port-channel with no changes
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ addr: 192.168.70.2/27
+ ipv6_dad: disabled
+ state: present
+ register: secondary_po_again
+
+ - name: Add secondary IP to routed interface vPC with no changes
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ side: A
+ addr: 192.168.90.2/27
+ ipv6_dad: disabled
+ state: present
+ register: secondary_vpc_again
+
+ - name: Verify MOs have not changed
+ assert:
+ that:
+ - secondary_intf_again is not changed
+ - secondary_po_again is not changed
+ - secondary_vpc_again is not changed
+
+ # CHECK updates/modifications
+ - name: Modify routed interface
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ addr: 192.168.50.2/27
+ ipv6_dad: enabled
+ state: present
+ register: secondary_intf_update
+
+ - name: Modify routed port-channel
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ addr: 192.168.70.2/27
+ ipv6_dad: enabled
+ state: present
+ register: secondary_po_update
+
+ - name: Modify routed vPC
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ side: A
+ addr: 192.168.90.2/27
+ ipv6_dad: enabled
+ state: present
+ register: secondary_vpc_update
+
+ - name: Verify updates have been applied
+ assert:
+ that:
+ - secondary_intf_update is changed
+ - secondary_po_update is changed
+ - secondary_vpc_update is changed
+ - secondary_intf_update.current.0.l3extIp.attributes.ipv6Dad == "enabled"
+ - secondary_po_update.current.0.l3extIp.attributes.ipv6Dad == "enabled"
+ - secondary_vpc_update.current.0.l3extIp.attributes.ipv6Dad == "enabled"
+
+ # QUERIES
+ - name: Query secondary for interface
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ addr: 192.168.50.2/27
+ ipv6_dad: enabled
+ state: query
+ register: secondary_intf_query
+
+ - name: Query secondary for po
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ addr: 192.168.70.2/27
+ ipv6_dad: enabled
+ state: query
+ register: secondary_po_query
+
+ - name: Query secondary for vpc
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ side: A
+ addr: 192.168.90.2/27
+ ipv6_dad: enabled
+ state: query
+ register: secondary_vpc_query
+
+ - name: Query all secondary IPs
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ state: query
+ register: secondary_all_query
+
+ - name: Verify queries
+ assert:
+ that:
+ - secondary_intf_query is not changed
+ - secondary_po_query is not changed
+ - secondary_vpc_query is not changed
+ - secondary_intf_query.current.0.l3extIp.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/addr-[192.168.50.2/27]"
+ - secondary_intf_query.current.0.l3extIp.attributes.ipv6Dad == "enabled"
+ - secondary_po_query.current.0.l3extIp.attributes.dn== "uni/tn-ansible_test/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/addr-[192.168.70.2/27]"
+ - secondary_po_query.current.0.l3extIp.attributes.ipv6Dad == "enabled"
+ - secondary_vpc_query.current.0.l3extIp.attributes.addr == "192.168.90.2/27"
+ - secondary_vpc_query.current.0.l3extIp.attributes.ipv6Dad == "enabled"
+ - secondary_all_query.current|length > 1
+
+ # DELETE secondary IPs
+ - name: Delete secondary for interface
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: eth1/15
+ addr: 192.168.50.2/27
+ ipv6_dad: enabled
+ state: absent
+ register: secondary_intf_remove
+
+ - name: Delete secondary for po
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201
+ path_ep: ansible_port_channel_ipg
+ addr: 192.168.70.2/27
+ ipv6_dad: enabled
+ state: absent
+ register: secondary_po_remove
+
+ - name: Delete secondary for vpc
+ aci_l3out_interface_secondary_ip:
+ <<: *aci_info
+ tenant: ansible_test
+ l3out: ansible_l3out
+ node_profile: ansible_node_profile
+ interface_profile: ansible_interface_profile
+ pod_id: 1
+ node_id: 201-202
+ path_ep: ansible_vpc_ipg
+ side: A
+ addr: 192.168.90.2/27
+ ipv6_dad: enabled
+ state: absent
+ register: secondary_vpc_remove
+
+ - name: Verify objects have been deleted
+ assert:
+ that:
+ - secondary_intf_remove.current == []
+ - secondary_po_remove.current == []
+ - secondary_vpc_remove.current == []
+ - secondary_intf_remove.previous.0.l3extIp.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[eth1/15]]/addr-[192.168.50.2/27]"
+ - secondary_po_remove.previous.0.l3extIp.attributes.dn == "uni/tn-ansible_test/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/rspathL3OutAtt-[topology/pod-1/paths-201/pathep-[ansible_port_channel_ipg]]/addr-[192.168.70.2/27]"
+ - secondary_vpc_remove.previous.0.l3extIp.attributes.addr == "192.168.90.2/27"
+
+ # CLEAN UP
+ - name: Remove tenant
+ aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+
+ - name: Remove ext domain
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_l3ext_domain
+ domain_type: l3dom
+ state: absent
+
+ - name: Remove port-channel
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: link
+ policy_group: ansible_port_channel_ipg
+ state: absent
+
+ - name: Remove vpc
+ aci_interface_policy_leaf_policy_group:
+ <<: *aci_info
+ lag_type: node
+ policy_group: ansible_vpc_ipg
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_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_logical_interface_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml
new file mode 100644
index 000000000..4466369d5
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile/tasks/main.yml
@@ -0,0 +1,174 @@
+# Author: Marcel Zehnder (@maercu)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant before we kickoff
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ tenant: ansible_test
+ 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
+ # SETUP ENVIRONMENT
+ - name: Create domain
+ cisco.aci.aci_domain: &domain_present
+ <<: *aci_info
+ domain: l3outintftest
+ domain_type: l3dom
+ state: present
+
+ - name: Create tenant
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Configure VRF
+ cisco.aci.aci_vrf: &vrf_present
+ <<: *tenant_present
+ vrf: l3outintftest
+
+ - name: Create L3Out
+ cisco.aci.aci_l3out:
+ <<: *vrf_present
+ l3out: l3outintftest
+ domain: l3outintftest
+ route_control: export
+
+ - name: Crete node profile
+ cisco.aci.aci_l3out_logical_node_profile: &np_present
+ <<: *tenant_present
+ l3out: l3outintftest
+ node_profile: NODES
+
+ # BEGIN WITH TESTS (ADD PROFILE)
+ - name: Add interface profile (check_mode)
+ cisco.aci.aci_l3out_logical_interface_profile: &intf_present
+ <<: *np_present
+ interface_profile: INTFS
+ check_mode: true
+ register: cm_add_intf
+
+ - name: Add interface profile (normal_mode)
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *intf_present
+ register: nm_add_intf
+
+ - name: Verify nm_add_intf
+ assert:
+ that:
+ - cm_add_intf is changed
+ - 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'
+ - nm_add_intf.current.0.l3extLIfP.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add profile again, check if idempotency works
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *intf_present
+ register: add_intf_again
+
+ - name: Verify add_intf_again
+ assert:
+ that:
+ - add_intf_again is not changed
+
+ # UPDATE INTERFACE PROFILE
+ - name: Update profile
+ cisco.aci.aci_l3out_logical_interface_profile: &intf_update
+ <<: *intf_present
+ nd_policy: NDTEST
+ register: update_intf
+
+ - name: Verify update_intf
+ assert:
+ that:
+ - update_intf is changed
+ - update_intf.previous != []
+
+ # ADD ANOTHER PROFILE
+ - name: Add another profile
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *intf_present
+ interface_profile: INTF2
+
+ # QUERY ALL PROFILES
+ - name: Query all profiles
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *aci_info
+ state: query
+ register: query_all_profiles
+
+ - name: Verify query_all_profiles
+ assert:
+ that:
+ - query_all_profiles is not changed
+ - query_all_profiles.current|length >= 1
+
+ # QUERY A SPECIFIC PROFILE
+ - name: Query a specific profile
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *intf_update
+ state: query
+ register: query_spec_profile
+
+ - name: Verify query_spec_profile
+ assert:
+ that:
+ - query_spec_profile is not changed
+ - query_spec_profile.current|length == 1
+
+ # QUERY A NON EXISTING PROFILE
+ - name: Query a nonexisting profile
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *np_present
+ interface_profile: nonexist
+ state: query
+ register: query_nonexist_profile
+
+ - name: Verify query_nonexist_profile
+ assert:
+ that:
+ - query_nonexist_profile is not changed
+ - query_nonexist_profile.current == []
+
+ # REMOVE PROFILE
+ - name: Remove interface profile
+ cisco.aci.aci_l3out_logical_interface_profile: &intf_absent
+ <<: *intf_update
+ state: absent
+ register: remove_profile
+
+ - name: Verify remove_profile
+ assert:
+ that:
+ - remove_profile is changed
+ - remove_profile.current == []
+
+ # REMOVE NONEXISTING PROFILE
+ - name: Remove interface profile again (nonexisting)
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *intf_absent
+ register: remove_nonexist_profile
+
+ - name: Verify remove_nonexist_profile
+ assert:
+ that:
+ - remove_nonexist_profile is not changed
+ - remove_nonexist_profile.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_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_logical_interface_profile_ospf_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml
new file mode 100644
index 000000000..d10a88a7f
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_profile_ospf_policy/tasks/main.yml
@@ -0,0 +1,172 @@
+# Author: Jason Juenger (@jasonjuenger)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant before we kickoff
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ tenant: ansible_test
+ 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
+ # SETUP ENVIRONMENT
+ - name: Create domain
+ cisco.aci.aci_domain: &domain_present
+ <<: *aci_info
+ domain: l3outintftest
+ domain_type: l3dom
+ state: present
+
+ - name: Create tenant
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Configure VRF
+ cisco.aci.aci_vrf: &vrf_present
+ <<: *tenant_present
+ vrf: l3outintftest
+
+ - name: Create L3Out
+ cisco.aci.aci_l3out:
+ <<: *vrf_present
+ l3out: l3outintftest
+ domain: l3outintftest
+ route_control: export
+
+ - name: Create node profile
+ cisco.aci.aci_l3out_logical_node_profile: &np_present
+ <<: *tenant_present
+ l3out: l3outintftest
+ node_profile: NODES
+
+ - name: Create interface profile
+ cisco.aci.aci_l3out_logical_interface_profile: &intf_present
+ <<: *np_present
+ interface_profile: INTFS
+
+ # BEGIN WITH TESTS (ADD OSPF POLICY TO PROFILE)
+ - name: Add ospf policy to interface profile (check mode)
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy: &ospfIfP_present
+ <<: *intf_present
+ ospf_policy: default
+ check_mode: true
+ register: cm_add_ospfIfP
+
+ - name: Add ospf policy to interface profile (normal mode)
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy: *ospfIfP_present
+ register: nm_add_ospfIfP
+
+ - name: Verify add_ospfIfP
+ assert:
+ that:
+ - cm_add_ospfIfP is changed
+ - nm_add_ospfIfP is changed
+ - cm_add_ospfIfP.previous == nm_add_ospfIfP.previous == []
+ - cm_add_ospfIfP.proposed.ospfIfP.children[0].ospfRsIfPol.attributes.tnOspfIfPolName == 'default'
+ - nm_add_ospfIfP.current[0].ospfIfP.children[0].ospfRsIfPol.attributes.tnOspfIfPolName == 'default'
+
+ - name: Add ospf policy again to check idempotency
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy: *ospfIfP_present
+ register: nm_add_ospfIfP_again
+
+ - name: Verify add_ospfIfP_again
+ assert:
+ that:
+ - nm_add_ospfIfP_again is not changed
+
+ # UPDATE INTERFACE PROFILE OSPF POLICY
+ - name: Update interface profile ospf policy
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy: &ospfIfP_update
+ <<: *ospfIfP_present
+ ospf_auth_type: simple
+ ospf_auth_key: my_key
+ register: update_ospfIfP
+
+ - name: Verify update_ospfIfP
+ assert:
+ that:
+ - update_ospfIfP is changed
+ - update_ospfIfP.previous != []
+ - update_ospfIfP.current[0].ospfIfP.children[0].ospfRsIfPol.attributes.tnOspfIfPolName == 'default'
+ - update_ospfIfP.current[0].ospfIfP.attributes.authType == 'simple'
+
+ # QUERY INTERFACE PROFILE OSPF POLICY
+ - name: Query interface profile ospf policy
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy:
+ <<: *ospfIfP_update
+ state: query
+ register: query_ospfIfP_profile
+
+ - name: Verify query_ospfIfP_profile
+ assert:
+ that:
+ - query_ospfIfP_profile is not changed
+ - query_ospfIfP_profile.current|length == 1
+ - query_ospfIfP_profile.current[0].ospfIfP.children[0].ospfRsIfPol.attributes.tnOspfIfPolName == 'default'
+ - query_ospfIfP_profile.current[0].ospfIfP.attributes.authType == 'simple'
+
+ # REMOVE POLICY
+ - name: Remove interface profile ospf policy
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy: &ospfIfP_absent
+ <<: *intf_present
+ state: absent
+ register: remove_profile
+
+ - name: Remove interface profile ospf policy again for idempotency
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy:
+ <<: *ospfIfP_absent
+ state: absent
+ register: remove_profile_again
+
+ - name: Verify remove_profile and remove_profile_again
+ assert:
+ that:
+ - remove_profile.previous|length == 1
+ - remove_profile.previous[0].ospfIfP.children[0].ospfRsIfPol.attributes.tnOspfIfPolName == 'default'
+ - remove_profile.previous[0].ospfIfP.attributes.authType == 'simple'
+ - remove_profile is changed
+ - remove_profile_again is not changed
+ - remove_profile.current == remove_profile_again.current == []
+
+ # QUERY NON-EXISTING POLICY
+ - name: Query a nonexisting policy
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy:
+ <<: *ospfIfP_absent
+ state: query
+ register: query_nonexist_policy
+
+ - name: Verify query_nonexist_policy
+ assert:
+ that:
+ - query_nonexist_policy is not changed
+ - query_nonexist_policy.current == []
+
+ # REMOVE NON-EXISTING POLICY
+ - name: Remove interface profile ospf policy again (nonexisting)
+ cisco.aci.aci_l3out_logical_interface_profile_ospf_policy:
+ <<: *ospfIfP_absent
+ register: remove_nonexist_policy
+
+ - name: Verify remove_nonexist_policy
+ assert:
+ that:
+ - remove_nonexist_policy is not changed
+ - remove_nonexist_policy.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/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_logical_interface_vpc_member/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml
new file mode 100644
index 000000000..749d2137f
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml
@@ -0,0 +1,149 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Anvitha Jain (@anvitha-jain)
+
+# 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: Add a new L3Out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ description: L3Out for ansible_tenant tenant
+ domain: ansible_dom
+ vrf: ansible_vrf
+ l3protocol: ospf
+ route_control: export
+ state: present
+
+ - name: Add a new logical node profile
+ cisco.aci.aci_l3out_logical_node_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_LNode
+ state: present
+
+ - name: Add a interface profile
+ cisco.aci.aci_l3out_logical_interface_profile:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_LNode
+ interface_profile: ansible_LInterface
+ state: present
+
+ - name: Add two vPC-interfaces
+ aci_l3out_interface:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_LNode
+ interface_profile: ansible_LInterface
+ pod_id: 1
+ node_id: 101-102
+ path_ep: "{{ item }}"
+ interface_type: ext-svi
+ state: present
+ loop:
+ - policy_group_one
+ - policy_group_two
+
+ - name: Add a VPC member based on path_dn
+ aci_l3out_logical_interface_vpc_member:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ logical_node: ansible_LNode
+ logical_interface: ansible_LInterface
+ path_dn: topology/pod-1/protpaths-101-102/pathep-[policy_group_one]
+ side: A
+ state: present
+ register: l3out_logical_interface_vpc_member_present
+
+ - name: Assertions check for add a VPC member based on path_dn
+ assert:
+ that:
+ - l3out_logical_interface_vpc_member_present is changed
+ - l3out_logical_interface_vpc_member_present.current.0.l3extMember.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add a VPC member based on pod_id, node_id, path_ep
+ aci_l3out_logical_interface_vpc_member:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ node_profile: ansible_LNode
+ interface_profile: ansible_LInterface
+ pod_id: 1
+ node_id: 101-102
+ path_ep: policy_group_two
+ side: A
+ addr: 192.168.1.254/24
+ ipv6_dad: disabled
+ state: present
+
+ - name: Query a specific VPC member under ansible_l3out
+ aci_l3out_logical_interface_vpc_member:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ logical_node: ansible_LNode
+ logical_interface: ansible_LInterface
+ path_dn: topology/pod-1/protpaths-101-102/pathep-[policy_group_one]
+ side: A
+ state: query
+ register: query_result
+
+ - name: Query all relationships
+ aci_l3out_logical_interface_vpc_member:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: query
+ ignore_errors: true
+ register: query_result
+
+ - name: Remove a VPC member
+ aci_l3out_logical_interface_vpc_member:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ logical_node: ansible_LNode
+ logical_interface: ansible_LInterface
+ path_dn: topology/pod-1/protpaths-101-102/pathep-[policy_group_one]
+ side: A
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_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_l3out_logical_node/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml
new file mode 100644
index 000000000..68bc64b20
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node/tasks/main.yml
@@ -0,0 +1,155 @@
+# Author: Marcel Zehnder (@maercu)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant before we kickoff
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ tenant: ansible_test
+ 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
+ # SETUP ENVIRONMENT
+ - name: Create domain
+ cisco.aci.aci_domain: &domain_present
+ <<: *aci_info
+ domain: l3outtest
+ domain_type: l3dom
+ state: present
+
+ - name: Create tenant
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Configure VRF
+ cisco.aci.aci_vrf: &vrf_present
+ <<: *tenant_present
+ vrf: l3outtest
+
+ - name: Create L3Out
+ cisco.aci.aci_l3out:
+ <<: *vrf_present
+ l3out: l3outtest
+ domain: l3outtest
+ route_control: export
+
+ - name: Crete node profile
+ cisco.aci.aci_l3out_logical_node_profile: &np_present
+ <<: *tenant_present
+ l3out: l3outtest
+ node_profile: NODES
+
+ # BEGIN WITH TESTS
+ - name: Add node (check_mode)
+ cisco.aci.aci_l3out_logical_node: &node_present
+ <<: *np_present
+ pod_id: 1
+ node_id: 111
+ router_id: 111.111.111.111
+ router_id_as_loopback: 'no'
+ check_mode: true
+ register: cm_add_node
+
+ - name: Add node (normal mode)
+ cisco.aci.aci_l3out_logical_node:
+ <<: *node_present
+ register: nm_add_node
+
+ - name: Verify nm_add_node
+ assert:
+ that:
+ - 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'
+ - nm_add_node.current.0.l3extRsNodeL3OutAtt.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add node again, check if idempotency works
+ cisco.aci.aci_l3out_logical_node:
+ <<: *node_present
+ register: add_node_again
+
+ - name: Verify add_node_again
+ assert:
+ that:
+ - add_node_again is not changed
+
+ # UPDATE NODE
+ - name: Change roouter id
+ cisco.aci.aci_l3out_logical_node: &node_update
+ <<: *node_present
+ router_id: 11.11.11.11
+ register: update_node
+
+ - name: Verify update_node
+ assert:
+ that:
+ - update_node is changed
+ - update_node.previous != []
+ - update_node.sent.l3extRsNodeL3OutAtt.attributes.rtrId == '11.11.11.11'
+
+ # ADD ANOTHER NODE
+ - name: Add another node
+ cisco.aci.aci_l3out_logical_node:
+ <<: *node_present
+ node_id: 112
+ router_id: 12.12.12.12
+
+ # QUERY ALL NODES
+ - name: Query all nodes
+ cisco.aci.aci_l3out_logical_node:
+ <<: *aci_info
+ state: query
+ register: query_all_nodes
+
+ - name: Verify query_all_nodes
+ assert:
+ that:
+ - query_all_nodes is not changed
+ - query_all_nodes.current|length >= 1
+
+ # QUERY A SPECIFIC NODE
+ - name: Query a specific node
+ cisco.aci.aci_l3out_logical_node:
+ <<: *node_update
+ state: query
+ register: query_spec_node
+
+ - name: Verify query_spec_node
+ assert:
+ that:
+ - query_spec_node is not changed
+ - query_spec_node.current|length == 1
+
+ # REMOVE NODE
+ - name: Remove node
+ cisco.aci.aci_l3out_logical_node:
+ <<: *node_update
+ state: absent
+ register: remove_node
+
+ - name: Verify remove_node
+ assert:
+ that:
+ - remove_node is changed
+ - remove_node.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_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_logical_node_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml
new file mode 100644
index 000000000..cbd3fa1a9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_node_profile/tasks/main.yml
@@ -0,0 +1,222 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Jason Juenger (@jasonjuenger)
+
+# 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_info
+ state: present
+ tenant: ansible_tenant
+ register: tenant_present
+
+ - name: Create L3out for tests
+ cisco.aci.aci_l3out:
+ <<: *aci_info
+ state: present
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ domain: ansible_dom
+ route_control: export
+ vrf: ansible_vrf
+ l3protocol: ospf
+ register: l3out_present
+
+ - name: Add L3out node profile (check mode)
+ cisco.aci.aci_l3out_logical_node_profile: &aci_node_profile_present
+ <<: *aci_info
+ node_profile: ansible_node_profile
+ description: 'Node profile for Ansible testing'
+ dscp: CS0
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: present
+ check_mode: true
+ register: cm_add_node_profile
+
+ - name: Add L3out node profile (normal mode)
+ cisco.aci.aci_l3out_logical_node_profile: *aci_node_profile_present
+ register: nm_add_node_profile
+
+ - name: Add another L3out node profile (normal mode)
+ cisco.aci.aci_l3out_logical_node_profile:
+ <<: *aci_info
+ node_profile: ansible_node_profile2
+ description: 'Second node profile for Ansible testing'
+ dscp: CS0
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: present
+ register: nm_add_second_node_profile
+
+ - name: Verify add_node_profile
+ assert:
+ that:
+ - cm_add_node_profile is changed
+ - nm_add_node_profile is changed
+ - nm_add_second_node_profile is changed
+ - cm_add_node_profile.sent.l3extLNodeP.attributes.descr == nm_add_node_profile.sent.l3extLNodeP.attributes.descr == 'Node profile for Ansible testing'
+ - cm_add_node_profile.sent.l3extLNodeP.attributes.name == nm_add_node_profile.sent.l3extLNodeP.attributes.name == 'ansible_node_profile'
+ - cm_add_node_profile.proposed.l3extLNodeP.attributes.descr == nm_add_node_profile.proposed.l3extLNodeP.attributes.descr == 'Node profile for Ansible testing'
+ - cm_add_node_profile.proposed.l3extLNodeP.attributes.name == nm_add_node_profile.proposed.l3extLNodeP.attributes.name == 'ansible_node_profile'
+ - cm_add_node_profile.current == cm_add_node_profile.previous == nm_add_node_profile.previous == []
+ - nm_add_node_profile.current.0.l3extLNodeP.attributes.dn == 'uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile'
+ - nm_add_node_profile.current.0.l3extLNodeP.attributes.name == 'ansible_node_profile'
+ - nm_add_node_profile.current.0.l3extLNodeP.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_second_node_profile.current.0.l3extLNodeP.attributes.dn == 'uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile2'
+ - nm_add_second_node_profile.current.0.l3extLNodeP.attributes.name == 'ansible_node_profile2'
+
+ - name: Modify node profile (check mode)
+ cisco.aci.aci_l3out_logical_node_profile: &aci_node_profile_modify
+ <<: *aci_info
+ node_profile: ansible_node_profile
+ description: 'my_updated_descr'
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: present
+ check_mode: true
+ register: cm_mod_node_profile
+
+ - name: Modify node profile (normal mode)
+ cisco.aci.aci_l3out_logical_node_profile: *aci_node_profile_modify
+ register: nm_mod_node_profile
+
+ - name: Verify mod_node_profile
+ assert:
+ that:
+ - cm_mod_node_profile is changed
+ - nm_mod_node_profile is changed
+ - cm_mod_node_profile.sent.l3extLNodeP.attributes.descr == nm_mod_node_profile.sent.l3extLNodeP.attributes.descr == 'my_updated_descr'
+ - cm_mod_node_profile.proposed.l3extLNodeP.attributes.descr == nm_mod_node_profile.proposed.l3extLNodeP.attributes.descr == 'my_updated_descr'
+ - nm_mod_node_profile.current.0.l3extLNodeP.attributes.dn == 'uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile'
+ - nm_mod_node_profile.current.0.l3extLNodeP.attributes.name == 'ansible_node_profile'
+
+ - name: Query existing node profile (check mode)
+ cisco.aci.aci_l3out_logical_node_profile: &query_existing_node_profile
+ <<: *aci_info
+ node_profile: ansible_node_profile
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: query
+ check_mode: true
+ register: cm_query_node_profile
+
+ - name: Query existing node profile (normal mode)
+ cisco.aci.aci_l3out_logical_node_profile: *query_existing_node_profile
+ register: nm_query_node_profile
+
+ - name: Query non-existent node profile
+ cisco.aci.aci_l3out_logical_node_profile:
+ <<: *aci_info
+ node_profile: ansible_fake_node_profile
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: query
+ check_mode: true
+ register: nm_query_fake_node_profile
+
+ - name: Query all node profile for L3out
+ cisco.aci.aci_l3out_logical_node_profile:
+ <<: *aci_info
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: query
+ register: nm_query_all_node_profiles
+
+ - name: Verify query_node_profile
+ assert:
+ that:
+ - cm_query_node_profile is not changed
+ - nm_query_node_profile is not changed
+ - nm_query_fake_node_profile is not changed
+ - nm_query_all_node_profiles is not changed
+ - cm_query_node_profile.current.0.l3extLNodeP.attributes.name == 'ansible_node_profile'
+ - nm_query_node_profile.current.0.l3extLNodeP.attributes.name == 'ansible_node_profile'
+ - nm_query_fake_node_profile.current == []
+ - nm_query_all_node_profiles.current.0.l3extOut.children.0.l3extLNodeP.attributes.name == 'ansible_node_profile2'
+ - nm_query_all_node_profiles.current.0.l3extOut.children.1.l3extLNodeP.attributes.name == 'ansible_node_profile'
+
+ - name: Remove node profile (check mode)
+ cisco.aci.aci_l3out_logical_node_profile: &aci_node_profile_absent
+ <<: *aci_info
+ node_profile: ansible_node_profile
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: absent
+ check_mode: true
+ register: cm_remove_node_profile
+
+ - name: Remove node profile (normal mode)
+ cisco.aci.aci_l3out_logical_node_profile: *aci_node_profile_absent
+ register: nm_remove_node_profile
+
+ - name: Remove node profile (normal mode) again
+ cisco.aci.aci_l3out_logical_node_profile: *aci_node_profile_absent
+ register: nm_remove_node_profile_again
+
+ - name: Remove second node profile (check mode)
+ cisco.aci.aci_l3out_logical_node_profile: &aci_second_node_profile_absent
+ <<: *aci_info
+ node_profile: ansible_node_profile2
+ l3out: ansible_l3out
+ tenant: ansible_tenant
+ state: absent
+ check_mode: true
+ register: cm_remove_second_node_profile
+
+ - name: Remove second node profile (normal mode)
+ cisco.aci.aci_l3out_logical_node_profile: *aci_second_node_profile_absent
+ register: nm_remove_second_node_profile
+
+ - name: Verify remove_node_profile
+ assert:
+ that:
+ - cm_remove_node_profile is changed
+ - cm_remove_second_node_profile is changed
+ - nm_remove_node_profile is changed
+ - nm_remove_node_profile_again is not changed
+ - nm_remove_second_node_profile is changed
+
+ # Remove L3out after testing
+ - name: Remove L3out (normal_mode)
+ cisco.aci.aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ state: absent
+
+ # Remove Tenant after testing
+ - name: Remove tenant (normal_mode)
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/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_static_routes/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml
new file mode 100644
index 000000000..147d180fc
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml
@@ -0,0 +1,258 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Anvitha Jain (@anvitha-jain)
+
+# 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: Add a new L3Out
+ aci_l3out:
+ <<: *aci_info
+ tenant: ansible_tenant
+ name: ansible_l3out
+ description: L3Out for ansible_tenant tenant
+ domain: ansible_dom
+ vrf: ansible_vrf
+ l3protocol: ospf
+ route_control: export
+ state: present
+
+ - name: Create L3OUT Logical Node Profile
+ cisco.aci.aci_l3out_logical_node_profile: &np_present
+ <<: *aci_info
+ node_profile: lNode
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ description: L3Out Logical Node Profile for ansible_tenant tenant
+ state: present
+
+ - name: Create L3OUT Logical Node
+ cisco.aci.aci_l3out_logical_node:
+ <<: *np_present
+ description: "{{ fake_var | default(omit) }}"
+ pod_id: 1
+ node_id: 101
+ router_id: 10.1.0.1
+ router_id_as_loopback: 'yes'
+ register: l3out_logical_node
+
+ - name: Verify l3out_logical_node
+ assert:
+ that:
+ - l3out_logical_node is changed
+ - l3out_logical_node.previous == []
+ - l3out_logical_node.sent.l3extRsNodeL3OutAtt.attributes.rtrId == '10.1.0.1'
+ - l3out_logical_node.sent.l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == 'yes'
+ - l3out_logical_node.sent.l3extRsNodeL3OutAtt.attributes.tDn == 'topology/pod-1/node-101'
+
+ - name: Add static routes (check_mode)
+ aci_l3out_static_routes: &route_present
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ logical_node: lNode
+ node_id: 101
+ pod_id: 1
+ prefix: 10.1.0.1/24
+ state: present
+ check_mode: true
+ register: cm_add_route
+
+ - name: Add static routes (normal_mode)
+ aci_l3out_static_routes:
+ <<: *route_present
+ register: nm_add_route
+
+ - name: Verify cm_add_route and nm_add_route
+ assert:
+ that:
+ - cm_add_route is changed
+ - nm_add_route is changed
+ - cm_add_route.proposed.ipRouteP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-lNode/rsnodeL3OutAtt-[topology/pod-1/node-101]/rt-[10.1.0.1/24]"
+ - nm_add_route.current[0].ipRouteP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-lNode/rsnodeL3OutAtt-[topology/pod-1/node-101]/rt-[10.1.0.1/24]"
+ - cm_add_route.proposed.ipRouteP.attributes.ip == "10.1.0.1/24"
+ - nm_add_route.current[0].ipRouteP.attributes.ip == "10.1.0.1/24"
+ - nm_add_route.current[0].ipRouteP.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add static routes again (check_mode)
+ aci_l3out_static_routes:
+ <<: *route_present
+ check_mode: true
+ register: cm_add_route_again
+
+ - name: Add static routes again (normal_mode)
+ aci_l3out_static_routes:
+ <<: *route_present
+ register: nm_add_route_again
+
+ - name: Verify cm_add_route_again and nm_add_route_again
+ assert:
+ that:
+ - cm_add_route_again is not changed
+ - nm_add_route_again is not changed
+ - cm_add_route_again.proposed.ipRouteP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-lNode/rsnodeL3OutAtt-[topology/pod-1/node-101]/rt-[10.1.0.1/24]"
+ - nm_add_route_again.current[0].ipRouteP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-lNode/rsnodeL3OutAtt-[topology/pod-1/node-101]/rt-[10.1.0.1/24]"
+ - cm_add_route_again.proposed.ipRouteP.attributes.ip == "10.1.0.1/24"
+ - nm_add_route_again.current[0].ipRouteP.attributes.ip == "10.1.0.1/24"
+
+ - name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+ - name: Add static routes with bfd
+ aci_l3out_static_routes:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ logical_node: lNode
+ node_id: 101
+ pod_id: 1
+ bfd: bfd
+ track_policy: test
+ prefix: 10.1.0.1/24
+ state: present
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+ register: nm_add_route_with_bfd
+
+ - name: Verify nm_add_route_with_bfd
+ assert:
+ that:
+ - nm_add_route_with_bfd is changed
+ - nm_add_route_with_bfd.current[0].ipRouteP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-lNode/rsnodeL3OutAtt-[topology/pod-1/node-101]/rt-[10.1.0.1/24]"
+ - nm_add_route_with_bfd.current[0].ipRouteP.attributes.ip == "10.1.0.1/24"
+ - nm_add_route_with_bfd.current[0].ipRouteP.attributes.rtCtrl == "bfd"
+ - nm_add_route_with_bfd.current[0].ipRouteP.children[0].ipRsRouteTrack.attributes.tDn == "uni/tn-ansible_tenant/tracklist-test"
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+
+ - name: Query for a specific MO under l3out
+ aci_l3out_static_routes:
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ logical_node: lNode
+ node_id: 101
+ pod_id: 1
+ prefix: 10.1.0.1/24
+ state: query
+ register: query_specific_mo
+
+ - name: Verify query_specific_mo
+ assert:
+ that:
+ - query_specific_mo is not changed
+ - query_specific_mo.current|length == 1
+ - query_specific_mo.current[0].ipRouteP.attributes.ip == "10.1.0.1/24"
+
+ - name: Query all relationships
+ aci_l3out_static_routes:
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: query
+ ignore_errors: true
+ register: query_all_relationships
+
+ - name: Verify query_all_relationships
+ assert:
+ that:
+ - query_all_relationships is not changed
+ - query_all_relationships.current|length == 1
+ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.attributes.name == "ansible_l3out"
+ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.attributes.name == "lNode"
+ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.children[0].l3extRsNodeL3OutAtt.attributes.rtrId == "10.1.0.1"
+ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.children[0].l3extRsNodeL3OutAtt.attributes.rtrIdLoopBack == "yes"
+ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.children[0].l3extRsNodeL3OutAtt.children[0].ipRouteP.attributes.ip == "10.1.0.1/24"
+ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.children[0].l3extRsNodeL3OutAtt.attributes.tDn == "topology/pod-1/node-101"
+
+ - name: Verify query_all_relationships for bfd
+ assert:
+ that:
+ - query_all_relationships.current[0].fvTenant.children[0].l3extOut.children[0].l3extLNodeP.children[0].l3extRsNodeL3OutAtt.children[0].ipRouteP.attributes.rtCtrl == "bfd"
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+
+ - name: Remove static routes (check_mode)
+ aci_l3out_static_routes: &route_absent
+ <<: *aci_info
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ logical_node: lNode
+ node_id: 101
+ pod_id: 1
+ prefix: 10.1.0.1/24
+ state: absent
+ check_mode: true
+ register: cm_remove_static_routes
+
+ - name: Remove static routes (normal_mode)
+ aci_l3out_static_routes:
+ <<: *route_absent
+ register: nm_remove_static_routes
+
+ - name: Verify cm_remove_static_routes and nm_remove_static_routes
+ assert:
+ that:
+ - cm_remove_static_routes is changed
+ - nm_remove_static_routes is changed
+ - cm_remove_static_routes.proposed == {}
+ - nm_remove_static_routes.current|length == 0
+
+ - name: Remove static routes again (check_mode)
+ aci_l3out_static_routes:
+ <<: *route_absent
+ check_mode: true
+ register: cm_remove_static_routes_again
+
+ - name: Remove static routes again (normal_mode)
+ aci_l3out_static_routes:
+ <<: *route_absent
+ register: nm_remove_static_routes_again
+
+ - name: Verify cm_remove_static_routes_again and nm_remove_static_routes_again
+ assert:
+ that:
+ - cm_remove_static_routes_again is not changed
+ - nm_remove_static_routes_again is not changed
+ - cm_remove_static_routes_again.proposed == {}
+ - nm_remove_static_routes_again.current|length == 0
+
+ - 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_l3out_static_routes_nexthop/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/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_static_routes_nexthop/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml
new file mode 100644
index 000000000..7d4de1a09
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes_nexthop/tasks/main.yml
@@ -0,0 +1,149 @@
+# Author: Marcel Zehnder (@maercu)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant before we kickoff
+ cisco.aci.aci_tenant: &tenant_absent
+ <<: *aci_info
+ tenant: ansible_test
+ 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
+ # SETUP ENVIRONMENT
+ - name: Create domain
+ cisco.aci.aci_domain: &domain_present
+ <<: *aci_info
+ domain: l3outtest
+ domain_type: l3dom
+ state: present
+
+ - name: Create tenant
+ cisco.aci.aci_tenant: &tenant_present
+ <<: *tenant_absent
+ state: present
+
+ - name: Configure VRF
+ cisco.aci.aci_vrf: &vrf_present
+ <<: *tenant_present
+ vrf: l3outtest
+
+ - name: Create L3Out
+ cisco.aci.aci_l3out:
+ <<: *vrf_present
+ l3out: l3outtest
+ domain: l3outtest
+ route_control: export
+
+ - name: Crete node profile
+ cisco.aci.aci_l3out_logical_node_profile: &np_present
+ <<: *tenant_present
+ l3out: l3outtest
+ node_profile: NODES
+
+ - name: Add node
+ cisco.aci.aci_l3out_logical_node: &node_present
+ <<: *np_present
+ pod_id: 1
+ node_id: 111
+ router_id: 111.111.111.111
+
+ - name: Add static route
+ cisco.aci.aci_l3out_static_routes: &prefix_present
+ <<: *np_present
+ pod_id: 1
+ node_id: 111
+ prefix: 10.10.0.0/16
+
+ # MODULE CHECKS
+ - name: Add a nexthop (check mode)
+ cisco.aci.aci_l3out_static_routes_nexthop: &nh_present
+ <<: *prefix_present
+ nexthop: 1.1.1.1
+ check_mode: true
+ register: cm_add_nh
+
+ - name: Add a nexthop (normal mode)
+ cisco.aci.aci_l3out_static_routes_nexthop:
+ <<: *nh_present
+ register: nm_add_nh
+
+ - name: Verify nm_add_nh
+ assert:
+ that:
+ - cm_add_nh is changed
+ - nm_add_nh is changed
+ - cm_add_nh.previous == nm_add_nh.previous == []
+ - cm_add_nh.sent.ipNexthopP.attributes.nhAddr == nm_add_nh.sent.ipNexthopP.attributes.nhAddr == '1.1.1.1'
+ - nm_add_nh.current.0.ipNexthopP.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add nexthop again, check if idempotency works
+ cisco.aci.aci_l3out_static_routes_nexthop:
+ <<: *nh_present
+ register: add_nh_again
+
+ - name: Verify add_nh_again
+ assert:
+ that:
+ - add_nh_again is not changed
+
+ # ADD ANOTHER NH
+ - name: Add another nexthop
+ cisco.aci.aci_l3out_static_routes_nexthop:
+ <<: *nh_present
+ nexthop: 1.1.1.2
+
+ # QUERY ALL NHs
+ - name: Query all nodes
+ cisco.aci.aci_l3out_static_routes_nexthop:
+ <<: *aci_info
+ state: query
+ register: query_all_nhs
+
+ - name: Verify query_all_nhs
+ assert:
+ that:
+ - query_all_nhs is not changed
+ - query_all_nhs.current|length >= 1
+
+ # QUERY A SPECIFIC NH
+ - name: Query a specific nexthop
+ cisco.aci.aci_l3out_static_routes_nexthop:
+ <<: *nh_present
+ state: query
+ register: query_spec_nh
+
+ - name: Verify query_spec_node
+ assert:
+ that:
+ - query_spec_nh is not changed
+ - query_spec_nh.current|length == 1
+
+ # REMOVE NH
+ - name: Remove nexthop
+ cisco.aci.aci_l3out_static_routes_nexthop:
+ <<: *nh_present
+ state: absent
+ register: remove_nh
+
+ - name: Verify remove_nh
+ assert:
+ that:
+ - remove_nh is changed
+ - remove_nh.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml
new file mode 100644
index 000000000..5660d0b87
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_lookup_interface_range/tasks/main.yml
@@ -0,0 +1,148 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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
+ 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: Sinlge string, single range
+ ansible.builtin.debug:
+ msg: "{{ item }}"
+ with_items: "{{ query('cisco.aci.interface_range', '5/0-2') }}"
+ register: single_string_single_range
+
+- name: Valid input assertions
+ assert:
+ that:
+ - single_string_single_range.results.0.item == "5/0"
+ - single_string_single_range.results.1.item == "5/1"
+ - single_string_single_range.results.2.item == "5/2"
+
+- name: Single string, multiple range
+ ansible.builtin.debug:
+ msg: "{{ item }}"
+ with_items: "{{ query('cisco.aci.interface_range', '1/1-4,2/10-15') }}"
+ register: single_string_multiple_interface
+
+- name: Valid input assertions
+ assert:
+ that:
+ - single_string_multiple_interface.results.0.item == "1/1"
+ - single_string_multiple_interface.results.1.item == "1/2"
+ - single_string_multiple_interface.results.2.item == "1/3"
+ - single_string_multiple_interface.results.3.item == "1/4"
+ - single_string_multiple_interface.results.4.item == "2/10"
+ - single_string_multiple_interface.results.5.item == "2/11"
+ - single_string_multiple_interface.results.6.item == "2/12"
+ - single_string_multiple_interface.results.7.item == "2/13"
+ - single_string_multiple_interface.results.8.item == "2/14"
+ - single_string_multiple_interface.results.9.item == "2/15"
+
+- name: Single string, single interface
+ ansible.builtin.debug:
+ msg: "{{ item }}"
+ with_items: "{{ query('cisco.aci.interface_range', '1/1') }}"
+ register: single_string_single_interface_as_range
+
+- name: Valid input assertions
+ assert:
+ that:
+ - single_string_single_interface_as_range.results.0.item == "1/1"
+
+- name: Multiple string, single and multiple range
+ ansible.builtin.debug:
+ msg: "{{ item }}"
+ with_items: "{{ query('cisco.aci.interface_range', '1/1-4,1/2/10-15', '2/3/4/5/2', '5/4-5') }}"
+ register: single_string_mix_ranges
+
+- name: Valid input assertions
+ assert:
+ that:
+ - single_string_mix_ranges.results.0.item == "1/1"
+ - single_string_mix_ranges.results.1.item == "1/2"
+ - single_string_mix_ranges.results.2.item == "1/2/10"
+ - single_string_mix_ranges.results.3.item == "1/2/11"
+ - single_string_mix_ranges.results.4.item == "1/2/12"
+ - single_string_mix_ranges.results.5.item == "1/2/13"
+ - single_string_mix_ranges.results.6.item == "1/2/14"
+ - single_string_mix_ranges.results.7.item == "1/2/15"
+ - single_string_mix_ranges.results.8.item == "1/3"
+ - single_string_mix_ranges.results.9.item == "1/4"
+ - single_string_mix_ranges.results.10.item == "2/3/4/5/2"
+ - single_string_mix_ranges.results.11.item == "5/4"
+ - single_string_mix_ranges.results.12.item == "5/5"
+
+- name: Invalid input not matching pattern
+ ansible.builtin.debug:
+ msg: "{{ item }}"
+ with_items: "{{ query('cisco.aci.interface_range', 'not matching pattern') }}"
+ ignore_errors: true
+ register: invalid_pattern
+
+- name: Invalid input end smaller than start
+ ansible.builtin.debug:
+ msg: "{{ item }}"
+ with_items: "{{ query('cisco.aci.interface_range', '1/4-1') }}"
+ ignore_errors: true
+ register: invalid_range_order
+
+- name: Invalid input assertions
+ assert:
+ that:
+ - "'Invalid range inputs,' in invalid_pattern.msg"
+ - "'Invalid range inputs,' in invalid_range_order.msg"
+
+- name: Leaf - Disable interfaces
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ pod_id: 1
+ node_id: 1101
+ interface: "{{ item }}"
+ state: present
+ with_items: "{{ query('cisco.aci.interface_range', '1/30-32') }}"
+ register: disable_leaf_int
+
+- name: Invalid input not matching pattern
+ ansible.builtin.debug:
+ msg: "{{ disable_leaf_int }}"
+
+- name: Valid disable interface assertions
+ assert:
+ that:
+ - disable_leaf_int.results.0.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+ - disable_leaf_int.results.0.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/30]"
+ - disable_leaf_int.results.1.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+ - disable_leaf_int.results.1.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/31]"
+ - disable_leaf_int.results.2.current.0.fabricRsOosPath.attributes.lc == "blacklist"
+ - disable_leaf_int.results.2.current.0.fabricRsOosPath.attributes.tDn == "topology/pod-1/paths-1101/pathep-[eth1/32]"
+
+- name: Leaf - Enable interfaces
+ cisco.aci.aci_interface_blacklist:
+ <<: *aci_info
+ pod_id: 1
+ node_id: 1101
+ interface: "{{ item }}"
+ state: absent
+ with_items: "{{ query('cisco.aci.interface_range', '1/30-32') }}"
+ register: enable_leaf_int
+
+- name: Valid enable interface assertions
+ assert:
+ that:
+ - enable_leaf_int.results.0.current == []
+ - enable_leaf_int.results.1.current == []
+ - enable_leaf_int.results.2.current == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml
new file mode 100644
index 000000000..310fc822b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_node_mgmt_epg/tasks/main.yml
@@ -0,0 +1,251 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: Remove node mgmt in_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: "{{ item }}"
+ encap: vlan-1
+ bd: bd1
+ state: absent
+ loop:
+ - ansible-inband
+ - ansible-inband-2
+
+ - name: Remove node mgmt out_of_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: "{{ item }}"
+ state: absent
+ loop:
+ - ansible-outofband
+ - ansible-outofband-2
+
+ # Add operations
+ - name: Add node mgmt in_band epg in check mode
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband
+ encap: vlan-1
+ bd: bd1
+ state: present
+ check_mode: true
+ register: add_cm_inband
+
+ - name: Add node mgmt out_of_band epg in check mode
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband
+ state: present
+ check_mode: true
+ register: add_cm_outofband
+
+ - name: Add node mgmt in_band epg in normal mode
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband
+ encap: vlan-1
+ bd: bd1
+ state: present
+ register: add_nm_inband
+
+ - name: Add node mgmt out_of_band epg in normal mode
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband
+ state: present
+ register: add_nm_outofband
+
+ - name: Add node mgmt in_band epg in normal mode again
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband
+ encap: vlan-1
+ bd: bd1
+ state: present
+ register: add_nm_inband_again
+
+ - name: Add node mgmt out_of_band epg in normal mode again
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband
+ state: present
+ register: add_nm_outofband_again
+
+ - name: Add another node mgmt in_band epg in normal mode
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband-2
+ encap: vlan-2
+ bd: bd2
+ state: present
+ register: add_nm_inband_2
+
+ - name: Add another node mgmt out_of_band epg in normal mode
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband-2
+ state: present
+ register: add_nm_outofband_2
+
+ - name: Add another node mgmt in_band epg in normal mode with change made to bd
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband-2
+ encap: vlan-2
+ bd: bd4
+ state: present
+ register: add_nm_inband_bd4
+
+ - name: Add another node mgmt in_band epg in normal mode with change made to encap
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband-2
+ encap: vlan-104
+ bd: bd4
+ state: present
+ register: add_nm_inband_encap4
+
+ - name: Verify add operations
+ assert:
+ that:
+ - add_cm_inband is changed
+ - add_cm_inband.sent.mgmtInB.attributes.name == 'ansible-inband'
+ - add_cm_inband.sent.mgmtInB.children.0.mgmtRsMgmtBD.attributes.tnFvBDName == 'bd1'
+ - add_cm_outofband is changed
+ - add_cm_outofband.sent.mgmtOoB.attributes.name == 'ansible-outofband'
+ - add_nm_inband is changed
+ - add_nm_inband.current.0.mgmtInB.attributes.name == 'ansible-inband'
+ - add_nm_inband.current.0.mgmtInB.children.0.mgmtRsMgmtBD.attributes.tnFvBDName == 'bd1'
+ - add_nm_inband.current.0.mgmtInB.attributes.annotation == 'orchestrator:ansible'
+ - add_nm_outofband is changed
+ - add_nm_outofband.current.0.mgmtOoB.attributes.name == 'ansible-outofband'
+ - add_nm_inband_again is not changed
+ - add_nm_inband_again.current.0.mgmtInB.attributes.name == 'ansible-inband'
+ - add_nm_outofband_again is not changed
+ - add_nm_outofband_again.current.0.mgmtOoB.attributes.name == 'ansible-outofband'
+ - add_nm_inband_2 is changed
+ - add_nm_inband_2.current.0.mgmtInB.attributes.name == 'ansible-inband-2'
+ - add_nm_inband_2.current.0.mgmtInB.children.0.mgmtRsMgmtBD.attributes.tnFvBDName == 'bd2'
+ - add_nm_outofband_2 is changed
+ - add_nm_outofband_2.current.0.mgmtOoB.attributes.name == 'ansible-outofband-2'
+ - add_nm_inband_bd4 is changed
+ - add_nm_inband_bd4.current.0.mgmtInB.children.0.mgmtRsMgmtBD.attributes.tnFvBDName == 'bd4'
+ - add_nm_inband_encap4 is changed
+ - add_nm_inband_encap4.current.0.mgmtInB.attributes.encap == 'vlan-104'
+
+ # Query operations
+ - name: Query node mgmt in_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband
+ encap: vlan-1
+ bd: bd1
+ state: query
+ register: query_inband
+
+ - name: Query node mgmt out_of_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband
+ state: query
+ register: query_outofband
+
+ - name: Query all in band
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ state: query
+ register: query_all_inband
+
+ - name: Query all out of band
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ state: query
+ register: query_all_outofband
+
+ - name: Verify query operations
+ assert:
+ that:
+ - query_inband is not changed
+ - query_inband.current.0.mgmtInB.attributes.name == 'ansible-inband'
+ - query_inband.current.0.mgmtInB.children.0.mgmtRsMgmtBD.attributes.tnFvBDName == 'bd1'
+ - query_outofband is not changed
+ - query_outofband.current.0.mgmtOoB.attributes.name == 'ansible-outofband'
+ - query_all_inband.current.0.mgmtMgmtP.children | length == 2
+ - query_all_outofband.current.0.mgmtMgmtP.children | length == 3
+
+ # Remove operations
+ - name: Remove node mgmt in_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband-2
+ state: absent
+ register: remove_inband_2
+
+ - name: Remove node mgmt out_of_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband-2
+ state: absent
+ register: remove_outofband_2
+
+ - name: Remove node mgmt in_band epg again
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband-2
+ state: absent
+ register: remove_inband_2_again
+
+ - name: Verify remove operations
+ assert:
+ that:
+ - remove_inband_2 is changed
+ - remove_inband_2.previous.0.mgmtInB.attributes.name == 'ansible-inband-2'
+ - remove_outofband_2 is changed
+ - remove_outofband_2.previous.0.mgmtOoB.attributes.name == 'ansible-outofband-2'
+ - remove_inband_2_again is not changed
+ - remove_inband_2_again.previous == [] \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_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_ntp_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml
new file mode 100644
index 000000000..ddc5b69e6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_policy/tasks/main.yml
@@ -0,0 +1,209 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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 any pre-existing NTP policy
+ cisco.aci.aci_ntp_policy: &policy_absent
+ <<: *aci_info
+ name: ansible_ntp_policy
+ state: absent
+
+# ADD NTP POLICY
+- name: Add NTP policy (check_mode)
+ cisco.aci.aci_ntp_policy: &policy_present
+ <<: *aci_info
+ name: ansible_ntp_policy
+ description: 'Ansible test policy'
+ admin_state: enabled
+ server_state: disabled
+ auth_state: disabled
+ state: present
+ check_mode: true
+ register: cm_add_policy
+
+- name: Add NTP policy (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_present
+ register: nm_add_policy
+
+- name: Add NTP policy again (check mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_present
+ check_mode: true
+ register: cm_add_policy_again
+
+- name: Add NTP policy again (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_present
+ register: nm_add_policy_again
+
+- name: Verify add policy
+ assert:
+ that:
+ - cm_add_policy is changed
+ - nm_add_policy is changed
+ - nm_add_policy.current.0.datetimePol.attributes.dn == 'uni/fabric/time-ansible_ntp_policy'
+ - nm_add_policy.current.0.datetimePol.attributes.name == 'ansible_ntp_policy'
+ - nm_add_policy.current.0.datetimePol.attributes.descr == 'Ansible test policy'
+ - nm_add_policy.current.0.datetimePol.attributes.adminSt == 'enabled'
+ - nm_add_policy.current.0.datetimePol.attributes.serverState == 'disabled'
+ - nm_add_policy.current.0.datetimePol.attributes.authSt == 'disabled'
+ - cm_add_policy_again is not changed
+ - nm_add_policy_again is not changed
+ - nm_add_policy_again.current.0.datetimePol.attributes.dn == 'uni/fabric/time-ansible_ntp_policy'
+ - nm_add_policy_again.current.0.datetimePol.attributes.name == 'ansible_ntp_policy'
+ - nm_add_policy_again.current.0.datetimePol.attributes.descr == 'Ansible test policy'
+ - nm_add_policy_again.current.0.datetimePol.attributes.adminSt == 'enabled'
+ - nm_add_policy_again.current.0.datetimePol.attributes.serverState == 'disabled'
+ - nm_add_policy_again.current.0.datetimePol.attributes.authSt == 'disabled'
+
+# MODIFY POLICY
+- name: Modify policy (check_mode)
+ cisco.aci.aci_ntp_policy: &policy_changed
+ <<: *aci_info
+ name: ansible_ntp_policy
+ description: 'Ansible updated test policy'
+ admin_state: enabled
+ server_state: enabled
+ auth_state: disabled
+ state: present
+ check_mode: true
+ register: cm_modify_policy
+
+- name: Modify policy (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_changed
+ register: nm_modify_policy
+
+- name: Modify policy again (check mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_changed
+ check_mode: true
+ register: cm_modify_policy_again
+
+- name: Modify policy again (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_changed
+ register: nm_modify_policy_again
+
+- name: Verify modify policy
+ assert:
+ that:
+ - cm_modify_policy is changed
+ - nm_modify_policy is changed
+ - nm_modify_policy.current.0.datetimePol.attributes.dn == 'uni/fabric/time-ansible_ntp_policy'
+ - nm_modify_policy.current.0.datetimePol.attributes.name == 'ansible_ntp_policy'
+ - nm_modify_policy.current.0.datetimePol.attributes.descr == 'Ansible updated test policy'
+ - nm_modify_policy.current.0.datetimePol.attributes.adminSt == 'enabled'
+ - nm_modify_policy.current.0.datetimePol.attributes.serverState == 'enabled'
+ - nm_modify_policy.current.0.datetimePol.attributes.authSt == 'disabled'
+ - cm_modify_policy_again is not changed
+ - nm_modify_policy_again is not changed
+ - nm_modify_policy_again.current.0.datetimePol.attributes.dn == 'uni/fabric/time-ansible_ntp_policy'
+ - nm_modify_policy_again.current.0.datetimePol.attributes.name == 'ansible_ntp_policy'
+ - nm_modify_policy_again.current.0.datetimePol.attributes.descr == 'Ansible updated test policy'
+ - nm_modify_policy_again.current.0.datetimePol.attributes.adminSt == 'enabled'
+ - nm_modify_policy_again.current.0.datetimePol.attributes.serverState == 'enabled'
+ - nm_modify_policy_again.current.0.datetimePol.attributes.authSt == 'disabled'
+
+# QUERY ALL POLICIES
+- name: Query all policies (check_mode)
+ cisco.aci.aci_ntp_policy: &policy_query_all
+ <<: *aci_info
+ state: query
+ check_mode: true
+ register: cm_query_all_policies
+
+- name: Query all policies (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_query_all
+ register: nm_query_all_policies
+
+- name: Verify query_all_policies
+ assert:
+ that:
+ - cm_query_all_policies is not changed
+ - nm_query_all_policies is not changed
+
+# QUERY OUR USER
+- name: Query our policy (check_mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_query_all
+ name: ansible_ntp_policy
+ check_mode: true
+ register: cm_query_policy
+
+- name: Query our policy (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_query_all
+ name: ansible_ntp_policy
+ register: nm_query_policy
+
+- name: Verify query_policy
+ assert:
+ that:
+ - cm_query_policy is not changed
+ - nm_query_policy is not changed
+ - cm_query_policy == nm_query_policy
+ - nm_query_policy.current.0.datetimePol.attributes.dn == 'uni/fabric/time-ansible_ntp_policy'
+ - nm_query_policy.current.0.datetimePol.attributes.name == 'ansible_ntp_policy'
+ - nm_query_policy.current.0.datetimePol.attributes.descr == 'Ansible updated test policy'
+ - nm_query_policy.current.0.datetimePol.attributes.adminSt == 'enabled'
+ - nm_query_policy.current.0.datetimePol.attributes.serverState == 'enabled'
+ - nm_query_policy.current.0.datetimePol.attributes.authSt == 'disabled'
+
+# REMOVE POLICY
+- name: Remove policy (check_mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_absent
+ check_mode: true
+ register: cm_remove_policy
+
+- name: Remove policy (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_absent
+ register: nm_remove_policy
+
+- name: Remove policy again (check_mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_absent
+ check_mode: true
+ register: cm_remove_policy_again
+
+- name: Remove policy again (normal mode)
+ cisco.aci.aci_ntp_policy:
+ <<: *policy_absent
+ register: nm_remove_policy_again
+
+- name: Verify remove_policy
+ assert:
+ that:
+ - cm_remove_policy is changed
+ - nm_remove_policy is changed
+ - nm_remove_policy.current == []
+ - nm_remove_policy.previous.0.datetimePol.attributes.dn == 'uni/fabric/time-ansible_ntp_policy'
+ - nm_remove_policy.previous.0.datetimePol.attributes.name == 'ansible_ntp_policy'
+ - nm_remove_policy.previous.0.datetimePol.attributes.descr == 'Ansible updated test policy'
+ - nm_remove_policy.previous.0.datetimePol.attributes.adminSt == 'enabled'
+ - nm_remove_policy.previous.0.datetimePol.attributes.serverState == 'enabled'
+ - nm_remove_policy.previous.0.datetimePol.attributes.authSt == 'disabled'
+ - cm_remove_policy_again is not changed
+ - nm_remove_policy_again is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml
new file mode 100644
index 000000000..15c6799cb
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_ntp_server/tasks/main.yml
@@ -0,0 +1,237 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, 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 any pre-existing NTP policy
+ cisco.aci.aci_ntp_policy: &policy_absent
+ <<: *aci_info
+ name: ansible_ntp_policy
+ state: absent
+
+# ADD NTP POLICY
+- name: Add NTP policy
+ cisco.aci.aci_ntp_policy:
+ <<: *aci_info
+ name: ansible_ntp_policy
+ description: 'Ansible test policy'
+ admin_state: enabled
+ server_state: disabled
+ auth_state: disabled
+ state: present
+
+# ADD NTP SERVER
+- name: Add NTP server (check mode)
+ cisco.aci.aci_ntp_server: &server_present
+ <<: *aci_info
+ ntp_policy: ansible_ntp_policy
+ ntp_server: 10.20.30.40
+ description: 'Ansible test server'
+ min_poll: 5
+ max_poll: 10
+ preferred: true
+ state: present
+ check_mode: true
+ register: cm_add_server
+
+- name: Add NTP server (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_present
+ register: nm_add_server
+
+- name: Add NTP server again (check mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_present
+ check_mode: true
+ register: cm_add_server_again
+
+- name: Add NTP server again (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_present
+ register: nm_add_server_again
+
+- name: Verify add server
+ assert:
+ that:
+ - cm_add_server is changed
+ - nm_add_server is changed
+ - nm_add_server.current.0.datetimeNtpProv.attributes.dn == 'uni/fabric/time-ansible_ntp_policy/ntpprov-10.20.30.40'
+ - nm_add_server.current.0.datetimeNtpProv.attributes.name == '10.20.30.40'
+ - nm_add_server.current.0.datetimeNtpProv.attributes.descr == 'Ansible test server'
+ - nm_add_server.current.0.datetimeNtpProv.attributes.minPoll == '5'
+ - nm_add_server.current.0.datetimeNtpProv.attributes.maxPoll == '10'
+ - nm_add_server.current.0.datetimeNtpProv.attributes.preferred == 'yes'
+ - cm_add_server_again is not changed
+ - nm_add_server_again is not changed
+ - nm_add_server_again.current.0.datetimeNtpProv.attributes.dn == 'uni/fabric/time-ansible_ntp_policy/ntpprov-10.20.30.40'
+ - nm_add_server_again.current.0.datetimeNtpProv.attributes.name == '10.20.30.40'
+ - nm_add_server_again.current.0.datetimeNtpProv.attributes.descr == 'Ansible test server'
+ - nm_add_server_again.current.0.datetimeNtpProv.attributes.minPoll == '5'
+ - nm_add_server_again.current.0.datetimeNtpProv.attributes.maxPoll == '10'
+ - nm_add_server_again.current.0.datetimeNtpProv.attributes.preferred == 'yes'
+
+# MODIFY SERVER
+- name: Modify NTP server (check mode)
+ cisco.aci.aci_ntp_server: &server_changed
+ <<: *aci_info
+ ntp_policy: ansible_ntp_policy
+ ntp_server: 10.20.30.40
+ description: 'Ansible test server'
+ min_poll: 6
+ max_poll: 9
+ preferred: true
+ epg_type: oob
+ epg_name: default
+ state: present
+ check_mode: true
+ register: cm_modify_server
+
+- name: Modify server (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_changed
+ register: nm_modify_server
+
+- name: Modify server again (check mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_changed
+ check_mode: true
+ register: cm_modify_server_again
+
+- name: Modify server again (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_changed
+ register: nm_modify_server_again
+
+- name: Verify modify policy
+ assert:
+ that:
+ - cm_modify_server is changed
+ - nm_modify_server is changed
+ - nm_modify_server.current.0.datetimeNtpProv.attributes.dn == 'uni/fabric/time-ansible_ntp_policy/ntpprov-10.20.30.40'
+ - nm_modify_server.current.0.datetimeNtpProv.attributes.name == '10.20.30.40'
+ - nm_modify_server.current.0.datetimeNtpProv.attributes.descr == 'Ansible test server'
+ - nm_modify_server.current.0.datetimeNtpProv.attributes.minPoll == '6'
+ - nm_modify_server.current.0.datetimeNtpProv.attributes.maxPoll == '9'
+ - nm_modify_server.current.0.datetimeNtpProv.attributes.preferred == 'yes'
+ - nm_modify_server.current.0.datetimeNtpProv.children.0.datetimeRsNtpProvToEpg.attributes.tDn == 'uni/tn-mgmt/mgmtp-default/oob-default'
+ - cm_modify_server_again is not changed
+ - nm_modify_server_again is not changed
+ - nm_modify_server_again.current.0.datetimeNtpProv.attributes.dn == 'uni/fabric/time-ansible_ntp_policy/ntpprov-10.20.30.40'
+ - nm_modify_server_again.current.0.datetimeNtpProv.attributes.name == '10.20.30.40'
+ - nm_modify_server_again.current.0.datetimeNtpProv.attributes.descr == 'Ansible test server'
+ - nm_modify_server_again.current.0.datetimeNtpProv.attributes.minPoll == '6'
+ - nm_modify_server_again.current.0.datetimeNtpProv.attributes.maxPoll == '9'
+ - nm_modify_server_again.current.0.datetimeNtpProv.attributes.preferred == 'yes'
+ - nm_modify_server_again.current.0.datetimeNtpProv.children.0.datetimeRsNtpProvToEpg.attributes.tDn == 'uni/tn-mgmt/mgmtp-default/oob-default'
+
+# QUERY ALL POLICIES
+- name: Query all servers (check_mode)
+ cisco.aci.aci_ntp_server: &server_query_all
+ <<: *aci_info
+ ntp_policy: ansible_ntp_policy
+ state: query
+ check_mode: true
+ register: cm_query_all_servers
+
+- name: Query all servers (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_query_all
+ register: nm_query_all_servers
+
+- name: Verify query_all_servers
+ assert:
+ that:
+ - cm_query_all_servers is not changed
+ - nm_query_all_servers is not changed
+
+# QUERY OUR SERVER
+- name: Query our server (check_mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_query_all
+ ntp_server: 10.20.30.40
+ check_mode: true
+ register: cm_query_server
+
+- name: Query our server (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_query_all
+ ntp_server: 10.20.30.40
+ register: nm_query_server
+
+- name: Verify query_server
+ assert:
+ that:
+ - cm_query_server is not changed
+ - nm_query_server is not changed
+ - cm_query_server == nm_query_server
+ - nm_query_server.current.0.datetimeNtpProv.attributes.dn == 'uni/fabric/time-ansible_ntp_policy/ntpprov-10.20.30.40'
+ - nm_query_server.current.0.datetimeNtpProv.attributes.name == '10.20.30.40'
+ - nm_query_server.current.0.datetimeNtpProv.attributes.descr == 'Ansible test server'
+ - nm_query_server.current.0.datetimeNtpProv.attributes.minPoll == '6'
+ - nm_query_server.current.0.datetimeNtpProv.attributes.maxPoll == '9'
+ - nm_query_server.current.0.datetimeNtpProv.attributes.preferred == 'yes'
+
+# REMOVE SERVER
+- name: Remove server (check mode)
+ cisco.aci.aci_ntp_server: &server_absent
+ <<: *aci_info
+ ntp_policy: ansible_ntp_policy
+ ntp_server: 10.20.30.40
+ state: absent
+ check_mode: true
+ register: cm_remove_server
+
+- name: Remove server (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_absent
+ register: nm_remove_server
+
+- name: Remove server again (check mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_absent
+ check_mode: true
+ register: cm_remove_server_again
+
+- name: Remove server again (normal mode)
+ cisco.aci.aci_ntp_server:
+ <<: *server_absent
+ register: nm_remove_server_again
+
+- name: Verify remove_server
+ assert:
+ that:
+ - cm_remove_server is changed
+ - nm_remove_server is changed
+ - nm_remove_server.current == []
+ - nm_remove_server.previous.0.datetimeNtpProv.attributes.dn == 'uni/fabric/time-ansible_ntp_policy/ntpprov-10.20.30.40'
+ - nm_remove_server.previous.0.datetimeNtpProv.attributes.name == '10.20.30.40'
+ - nm_remove_server.previous.0.datetimeNtpProv.attributes.descr == 'Ansible test server'
+ - nm_remove_server.previous.0.datetimeNtpProv.attributes.minPoll == '6'
+ - nm_remove_server.previous.0.datetimeNtpProv.attributes.maxPoll == '9'
+ - nm_remove_server.previous.0.datetimeNtpProv.attributes.preferred == 'yes'
+ - cm_remove_server_again is not changed
+ - nm_remove_server_again is not changed
+
+# CLEAN UP
+- name: Remove NTP Policy
+ cisco.aci.aci_ntp_policy:
+ <<: *aci_info
+ name: ansible_ntp_policy
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..1c503c5f2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml
@@ -0,0 +1,230 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# PROVOKE ERRORS
+- name: Error on name resolution
+ cisco.aci.aci_rest:
+ host: foo.bar.cisco.com
+ 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
+ path: /api/mo/uni.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ ignore_errors: true
+ register: error_on_name_resolution
+
+- name: Verify error_on_name_resolution
+ 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:")
+ - "'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
+ 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: debug
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ ignore_errors: true
+ register: error_on_missing_required_param
+
+- name: Verify error_on_missing_required_param
+ assert:
+ that:
+ - error_on_missing_required_param is failed
+ - 'error_on_missing_required_param.msg == "missing required arguments: path"'
+ - "'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
+ 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: debug
+ path: /api/mo/uni/tn-ansible_test.json
+ method: post
+ content:
+ fvTenant:
+ children:
+ ignore_errors: true
+ register: error_on_missing_attributes
+
+- name: Verify error_on_missing_attributes
+ assert:
+ that:
+ - error_on_missing_attributes is failed
+ - error_on_missing_attributes.method == 'POST'
+ - "error_on_missing_attributes.msg == 'APIC Error 400: invalid data at line \\'1\\'. Attributes are missing, tag \\'attributes\\' must be specified first, before any other tag'"
+ - 'error_on_missing_attributes.response == "HTTP Error 400: Bad Request"'
+ - error_on_missing_attributes.status == 400
+ - "'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
+ 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: debug
+ path: /api/mo/uni.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ descr: This is an [invalid] description
+ ignore_errors: true
+ register: error_on_input_validation
+
+- name: Verify error_on_input_validation
+ assert:
+ that:
+ - error_on_input_validation is failed
+ - error_on_input_validation.method == 'POST'
+ - "error_on_input_validation.msg == 'APIC Error 801: property descr of tn-ansible_test failed validation for value \\'This is an [invalid] description\\''"
+ - 'error_on_input_validation.response == "HTTP Error 400: Bad Request"'
+ - error_on_input_validation.status == 400
+ - "'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
+ 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: debug
+ path: /api/mo/uni.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ description: This is an "invalid" description
+ ignore_errors: true
+ register: error_on_invalid_attributes
+
+- name: Verify error_on_invalid_attributes
+ assert:
+ that:
+ - error_on_invalid_attributes is failed
+ - error_on_invalid_attributes.method == 'POST'
+ - "error_on_invalid_attributes.msg == 'APIC Error 400: unknown attribute \\'description\\' in element \\'fvTenant\\''"
+ - 'error_on_invalid_attributes.response == "HTTP Error 400: Bad Request"'
+ - error_on_invalid_attributes.status == 400
+ - "'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
+ 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: debug
+ path: /api/mo/uni.json
+ method: post
+ content:
+ fvFoobar:
+ attributes:
+ name: ansible_test
+ ignore_errors: true
+ register: error_on_invalid_object
+
+- name: Verify error_on_invalid_object
+ assert:
+ that:
+ - error_on_invalid_object is failed
+ - error_on_invalid_object.method == 'POST'
+ - "error_on_invalid_object.msg == 'APIC Error 122: unknown managed object class fvFoobar'"
+ - 'error_on_invalid_object.response == "HTTP Error 400: Bad Request"'
+ - error_on_invalid_object.status == 400
+ - "'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
+# Avoiding error: TypeError: must be str, not bytes
+- name: Add user certificate
+ cisco.aci.aci_aaa_user_certificate:
+ 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: '{{ aci_username }}'
+ name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+ register: cm_add_cert
+
+- name: Create tenant
+ cisco.aci.aci_rest: &tenant
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ certificate_name: admin
+ private_key: "{{ lookup('file', 'pki/admin.key') }}"
+ 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="test_tenant_cert_auth"/>
+
+- name: Delete tenant
+ cisco.aci.aci_rest:
+ <<: *tenant
+ content:
+ <fvTenant name="test_tenant_cert_auth" status="deleted"/> \ No newline at end of file
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
new file mode 100644
index 000000000..dd27525f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml
@@ -0,0 +1,166 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: delete
+
+# ADD TENANT
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: &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: '{{ aci_output_level | default("info") }}'
+ path: /api/mo/uni.json
+ method: post
+ content:
+ {
+ "fvTenant": {
+ "attributes": {
+ "name": "ansible_test"
+ }
+ }
+ }
+ delegate_to: localhost
+ 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
+ assert:
+ that:
+ - nm_add_tenant is changed
+ - nm_add_tenant_again is not changed
+
+# CHANGE TENANT
+- name: Change description of tenant (normal mode)
+ cisco.aci.aci_rest: &tenant_changed
+ 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.json
+ method: post
+ content:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Ansible test tenant",
+ "name": "ansible_test"
+ }
+ }
+ }
+ 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
+ assert:
+ that:
+ - nm_add_tenant_descr is changed
+ - nm_add_tenant_descr_again is not changed
+
+# 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
+ assert:
+ that:
+ - nm_add_tenant_again_no_descr is not changed
+
+# QUERY ALL TENANTS
+- name: Query all tenants (normal mode)
+ cisco.aci.aci_rest: &tenant_query_all
+ 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/tn-[ansible_test].json
+ method: get
+ delegate_to: localhost
+ register: nm_query_all_tenants
+
+- name: Verify query_all_tenants
+ assert:
+ that:
+ - nm_query_all_tenants is not changed
+
+# QUERY A TENANT
+- name: Query our tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: get
+ delegate_to: localhost
+ register: nm_query_tenant
+
+- name: Verify query_tenant
+ assert:
+ that:
+ - nm_query_tenant is not changed
+
+# 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
+ assert:
+ that:
+ - nm_remove_tenant is changed
+ - nm_remove_tenant_again is not changed
+
+# 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
+ assert:
+ that:
+ - nm_query_non_tenant is not changed
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
new file mode 100644
index 000000000..bbbd57cd4
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml
@@ -0,0 +1,157 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: delete
+
+# ADD TENANT
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: &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: '{{ aci_output_level | default("info") }}'
+ path: /api/mo/uni.json
+ method: post
+ content: |
+ {
+ "fvTenant": {
+ "attributes": {
+ "name": "ansible_test"
+ }
+ }
+ }
+ output_path: "/tmp/ansible_output_file.log"
+ register: nm_add_tenant
+
+- name: Add tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_present
+ register: nm_add_tenant_again
+
+- name: Verify add_tenant
+ assert:
+ that:
+ - nm_add_tenant is changed
+ - nm_add_tenant_again is not changed
+
+# CHANGE TENANT
+- name: Change description of tenant (normal mode)
+ cisco.aci.aci_rest: &tenant_changed
+ 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.json
+ method: post
+ content: |
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Ansible test tenant",
+ "name": "ansible_test"
+ }
+ }
+ }
+ register: nm_add_tenant_descr
+
+- name: Change description of tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_changed
+ register: nm_add_tenant_descr_again
+
+- name: Verify add_tenant_descr
+ assert:
+ that:
+ - nm_add_tenant_descr is changed
+ - nm_add_tenant_descr_again is not changed
+
+# ADD TENANT AGAIN
+- name: Add tenant again with no description (normal mode)
+ cisco.aci.aci_rest: *tenant_present
+ register: nm_add_tenant_again_no_descr
+
+- name: Verify add_tenant_again_no_descr
+ assert:
+ that:
+ - nm_add_tenant_again_no_descr is not changed
+
+# QUERY ALL TENANTS
+- name: Query all tenants (normal mode)
+ cisco.aci.aci_rest: &tenant_query_all
+ 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/tn-[ansible_test].json
+ method: get
+ register: nm_query_all_tenants
+
+- name: Verify query_all_tenants
+ assert:
+ that:
+ - nm_query_all_tenants is not changed
+
+# QUERY A TENANT
+- name: Query our tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: get
+ register: nm_query_tenant
+
+- name: Verify query_tenant
+ assert:
+ that:
+ - nm_query_tenant is not changed
+
+# REMOVE TENANT
+- name: Remove tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant
+
+- name: Remove tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant_again
+
+- name: Verify remove_tenant
+ assert:
+ that:
+ - nm_remove_tenant is changed
+ - nm_remove_tenant_again is not changed
+
+# QUERY NON-EXISTING TENANT
+- name: Query non-existing tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_query
+ register: nm_query_non_tenant
+
+- name: Verify query_non_tenant
+ assert:
+ that:
+ - nm_query_non_tenant is not changed
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
new file mode 100644
index 000000000..0952dd85b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml
@@ -0,0 +1,31 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+# Copyright: (c) 2020, Cindy Zhao (@cizhao) <cizhao@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
+
+- include_tasks: yaml_inline.yml
+ tags: yaml_inline
+
+- include_tasks: yaml_string.yml
+ tags: yaml_string
+
+- include_tasks: json_inline.yml
+ tags: json_inline
+
+- include_tasks: json_string.yml
+ tags: json_string
+
+- include_tasks: xml_string.yml
+ tags: xml_string
+
+- include_tasks: error_handling.yml
+ tags: error_handling
+
+- include_tasks: xml_file.yml
+ tags: xml_file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/pki/admin.crt b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/pki/admin.crt
new file mode 100644
index 000000000..cfac5531e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/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_rest/tasks/pki/admin.key b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/pki/admin.key
new file mode 100644
index 000000000..63bb00cc0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/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_rest/tasks/xml_file.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml
new file mode 100644
index 000000000..cdde037c4
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_file.yml
@@ -0,0 +1,214 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, Sabari Jaganathan (@sajagana) <sajagana@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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("debug") }}'
+ output_path: "/tmp/ansible_output_file.log"
+
+- name: Ensure tenant does not exists using ans_test_delete xml template
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml"
+ method: post
+
+- name: Add tenant using ans_test_create xml template file with check mode
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml"
+ method: post
+ check_mode: true
+ register: cm_add_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
+
+- name: Add tenant using ans_test_create xml template file with normal mode
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml"
+ method: post
+ register: nm_add_tenant
+
+- name: Assertions check for add tenant using ans_test_create xml template file with normal mode
+ assert:
+ that:
+ - nm_add_tenant is changed
+ - nm_add_tenant.imdata.0.fvTenant.attributes.name == "ans_test_create"
+ - nm_add_tenant.imdata.0.fvTenant.attributes.descr == "ans_test_create tenant created successfully"
+ - nm_add_tenant.imdata.0.fvTenant.attributes.dn == "uni/tn-ans_test_create"
+ - nm_add_tenant.imdata.0.fvTenant.children != []
+
+- name: Add tenant using ans_test_create xml template file with normal mode - idempotency works
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml"
+ method: post
+ register: idempotency_nm_add_tenant
+
+- name: Idempotency assertions check for add tenant using ans_test_create xml template file with normal mode
+ assert:
+ that:
+ - idempotency_nm_add_tenant is not changed
+
+- name: Query ans_test_create tenant using query string after the create
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: "/api/node/mo/uni/tn-ans_test_create.json?query-target=self"
+ method: get
+ register: query_ans_test_create
+
+- name: Assertions check for querying ans_test_create tenant using query string after the create
+ assert:
+ that:
+ - query_ans_test_create is not changed
+ - query_ans_test_create.imdata != []
+ - query_ans_test_create.imdata.0.fvTenant.attributes.name == "ans_test_create"
+ - query_ans_test_create.imdata.0.fvTenant.attributes.descr == "ans_test_create tenant created successfully"
+ - query_ans_test_create.imdata.0.fvTenant.attributes.dn == "uni/tn-ans_test_create"
+
+- name: Update tenant description using ans_test_update xml template file with check mode
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml"
+ method: post
+ check_mode: true
+ register: cm_update_tenant
+
+- 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
+
+- name: Update tenant description using ans_test_update xml template file with normal mode
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml"
+ method: post
+ register: nm_update_tenant
+
+- name: Assertions check for update tenant description using ans_test_update xml template file with normal mode
+ assert:
+ that:
+ - nm_update_tenant is changed
+ - nm_update_tenant.imdata.0.fvTenant.attributes.name == "ans_test_create"
+ - nm_update_tenant.imdata.0.fvTenant.attributes.descr == "ans_test_create tenant updated successfully"
+ - nm_update_tenant.imdata.0.fvTenant.attributes.dn == "uni/tn-ans_test_create"
+
+- name: Update tenant description using ans_test_update xml template file with normal mode - idempotency works
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml"
+ method: post
+ register: idempotency_nm_update_tenant
+
+- name: Idempotency assertions check for update tenant description using ans_test_update xml template file with normal mode
+ assert:
+ that:
+ - idempotency_nm_update_tenant is not changed
+
+- name: Query ans_test_create tenant using query string after the update
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: "/api/node/mo/uni/tn-ans_test_create.json?query-target=self"
+ method: get
+ register: query_ans_test_update
+
+- name: Assertions check for querying ans_test_create tenant using query string after the update
+ assert:
+ that:
+ - query_ans_test_update is not changed
+ - query_ans_test_update.imdata != []
+ - query_ans_test_update.imdata.0.fvTenant.attributes.name == "ans_test_create"
+ - query_ans_test_update.imdata.0.fvTenant.attributes.descr == "ans_test_create tenant updated successfully"
+ - query_ans_test_update.imdata.0.fvTenant.attributes.dn == "uni/tn-ans_test_create"
+
+- name: Update tenant name using ans_test_negative_update_check xml template file with normal mode
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_negative_update_check.xml"
+ method: post
+ register: negative_update_tenant_check
+ ignore_errors: true
+
+- name: Assertions check for update tenant name using ans_test_negative_update_check xml template file with normal mode
+ assert:
+ that:
+ - negative_update_tenant_check is failed
+
+- name: Delete tenant using ans_test_delete xml template file with check mode
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml"
+ method: post
+ check_mode: true
+ register: cm_delete_tenant
+
+- name: Assertions check for delete tenant using ans_test_delete xml template file with check mode
+ assert:
+ that:
+ - cm_delete_tenant is not changed
+
+- name: Delete tenant using ans_test_delete xml template file with normal mode
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml"
+ method: post
+ register: nm_delete_tenant
+
+- name: Assertions check for delete tenant using ans_test_delete xml template file with normal mode
+ assert:
+ that:
+ - nm_delete_tenant is changed
+ - nm_delete_tenant.imdata.0.fvTenant.attributes.name == "ans_test_create"
+ - nm_delete_tenant.imdata.0.fvTenant.attributes.descr == "ans_test_create tenant updated successfully"
+ - nm_delete_tenant.imdata.0.fvTenant.attributes.dn == "uni/tn-ans_test_create"
+
+- name: Delete tenant using ans_test_delete xml template file with normal mode - idempotency works
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni.xml
+ src: "./targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml"
+ method: post
+ register: idempotency_nm_delete_tenant
+
+- name: Idempotency assertions check for delete tenant using ans_test_delete xml template file with normal mode
+ assert:
+ that:
+ - idempotency_nm_delete_tenant is not changed
+ - idempotency_nm_delete_tenant.imdata == {}
+
+- name: Query ans_test_create tenant using query string after the delete
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: "/api/node/mo/uni/tn-ans_test_create.json?query-target=self"
+ method: get
+ register: query_ans_test_delete
+
+- name: Assertions check for querying ans_test_create tenant using query string after the delete
+ assert:
+ that:
+ - query_ans_test_delete is not changed
+ - query_ans_test_delete.imdata == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml
new file mode 100644
index 000000000..b5d25b3d8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_create.xml
@@ -0,0 +1 @@
+<fvTenant descr="ans_test_create tenant created successfully" dn="uni/tn-ans_test_create" name="ans_test_create" status=""/> \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml
new file mode 100644
index 000000000..9e6c9028e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_delete.xml
@@ -0,0 +1 @@
+<fvTenant dn="uni/tn-ans_test_create" status="deleted"/> \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_negative_update_check.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_negative_update_check.xml
new file mode 100644
index 000000000..f2d5a040d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_negative_update_check.xml
@@ -0,0 +1 @@
+<fvTenant descr="ans_test_create tenant updated successfully" dn="uni/tn-ans_test_create" name="ans_test_update" status="modified"/> \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml
new file mode 100644
index 000000000..99b0a5911
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_files/tn-ans_test_update.xml
@@ -0,0 +1 @@
+<fvTenant descr="ans_test_create tenant updated successfully" dn="uni/tn-ans_test_create" name="ans_test_create" status="modified"/> \ 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
new file mode 100644
index 000000000..c87291779
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml
@@ -0,0 +1,167 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].xml
+ method: delete
+
+# ADD TENANT
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: &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: '{{ aci_output_level | default("info") }}'
+ path: /api/mo/uni.xml
+ method: post
+ content:
+ {
+ "fvTenant": {
+ "attributes": {
+ "name": "ansible_test"
+ }
+ }
+ }
+ register: nm_add_tenant
+
+- name: Add tenant again (normal mode)
+ cisco.aci.aci_rest:
+ <<: *tenant_present
+ path: /api/mo/uni.xml
+ content:
+ <fvTenant name="ansible_test"/>
+ register: nm_add_tenant_again
+
+- name: Verify add_tenant
+ assert:
+ that:
+ - nm_add_tenant is changed
+ - nm_add_tenant_again is not changed
+
+# CHANGE TENANT
+- name: Change description of tenant (normal mode)
+ cisco.aci.aci_rest: &tenant_changed
+ 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
+ descr: Ansible test tenant
+ register: nm_add_tenant_descr
+
+- name: Change description of tenant again (normal mode)
+ cisco.aci.aci_rest:
+ <<: *tenant_changed
+ path: /api/mo/uni.xml
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ descr: Ansible test tenant
+ register: nm_add_tenant_descr_again
+
+- name: Verify add_tenant_descr
+ assert:
+ that:
+ - nm_add_tenant_descr is changed
+ - nm_add_tenant_descr_again is not changed
+
+# ADD TENANT AGAIN
+- name: Add tenant again with no description (normal mode)
+ cisco.aci.aci_rest:
+ <<: *tenant_present
+ path: /api/mo/uni.xml
+ content:
+ <fvTenant name="ansible_test"/>
+ register: nm_add_tenant_again_no_descr
+
+- name: Verify add_tenant_again_no_descr
+ assert:
+ that:
+ - nm_add_tenant_again_no_descr is not changed
+
+# QUERY ALL TENANTS
+- name: Query all tenants (normal mode)
+ cisco.aci.aci_rest: &tenant_query_all
+ 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/tn-[ansible_test].xml
+ method: get
+ register: nm_query_all_tenants
+
+- name: Verify query_all_tenants
+ assert:
+ that:
+ - nm_query_all_tenants is not changed
+
+# QUERY A TENANT
+- name: Query our tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].xml
+ method: get
+ register: nm_query_tenant
+
+- name: Verify query_tenant
+ assert:
+ that:
+ - nm_query_tenant is not changed
+
+# REMOVE TENANT
+- name: Remove tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant
+
+- name: Remove tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant_again
+
+- name: Verify remove_tenant
+ assert:
+ that:
+ - nm_remove_tenant is changed
+ - nm_remove_tenant_again is not changed
+
+# QUERY NON-EXISTING TENANT
+- name: Query non-existing tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_query
+ register: nm_query_non_tenant
+
+- name: Verify query_non_tenant
+ assert:
+ that:
+ - nm_query_non_tenant is not changed
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
new file mode 100644
index 000000000..d7538f9a6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml
@@ -0,0 +1,148 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: delete
+
+# ADD TENANT
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: &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: '{{ aci_output_level | default("info") }}'
+ path: /api/mo/uni.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ register: nm_add_tenant
+
+- name: Add tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_present
+ register: nm_add_tenant_again
+
+- name: Verify add_tenant
+ assert:
+ that:
+ - nm_add_tenant is changed
+ - nm_add_tenant_again is not changed
+
+# CHANGE TENANT
+- name: Change description of tenant (normal mode)
+ cisco.aci.aci_rest: &tenant_changed
+ 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.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ descr: Ansible test tenant
+ register: nm_add_tenant_descr
+
+- name: Change description of tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_changed
+ register: nm_add_tenant_descr_again
+
+- name: Verify add_tenant_descr
+ assert:
+ that:
+ - nm_add_tenant_descr is changed
+ - nm_add_tenant_descr_again is not changed
+
+# ADD TENANT AGAIN
+- name: Add tenant again with no description (normal mode)
+ cisco.aci.aci_rest: *tenant_present
+ register: nm_add_tenant_again_no_descr
+
+- name: Verify add_tenant_again_no_descr
+ assert:
+ that:
+ - nm_add_tenant_again_no_descr is not changed
+
+# QUERY ALL TENANTS
+- name: Query all tenants (normal mode)
+ cisco.aci.aci_rest: &tenant_query_all
+ 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/tn-[ansible_test].json
+ method: get
+ register: nm_query_all_tenants
+
+- name: Verify query_all_tenants
+ assert:
+ that:
+ - nm_query_all_tenants is not changed
+
+# QUERY A TENANT
+- name: Query our tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: get
+ register: nm_query_tenant
+
+- name: Verify query_tenant
+ assert:
+ that:
+ - nm_query_tenant is not changed
+
+# REMOVE TENANT
+- name: Remove tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant
+
+- name: Remove tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant_again
+
+- name: Verify remove_tenant
+ assert:
+ that:
+ - nm_remove_tenant is changed
+ - nm_remove_tenant_again is not changed
+
+# QUERY NON-EXISTING TENANT
+- name: Query non-existing tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_query
+ register: nm_query_non_tenant
+
+- name: Verify query_non_tenant
+ assert:
+ that:
+ - nm_query_non_tenant is not changed
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
new file mode 100644
index 000000000..d7538f9a6
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml
@@ -0,0 +1,148 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: delete
+
+# ADD TENANT
+- name: Add tenant (normal mode)
+ cisco.aci.aci_rest: &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: '{{ aci_output_level | default("info") }}'
+ path: /api/mo/uni.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ register: nm_add_tenant
+
+- name: Add tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_present
+ register: nm_add_tenant_again
+
+- name: Verify add_tenant
+ assert:
+ that:
+ - nm_add_tenant is changed
+ - nm_add_tenant_again is not changed
+
+# CHANGE TENANT
+- name: Change description of tenant (normal mode)
+ cisco.aci.aci_rest: &tenant_changed
+ 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.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: ansible_test
+ descr: Ansible test tenant
+ register: nm_add_tenant_descr
+
+- name: Change description of tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_changed
+ register: nm_add_tenant_descr_again
+
+- name: Verify add_tenant_descr
+ assert:
+ that:
+ - nm_add_tenant_descr is changed
+ - nm_add_tenant_descr_again is not changed
+
+# ADD TENANT AGAIN
+- name: Add tenant again with no description (normal mode)
+ cisco.aci.aci_rest: *tenant_present
+ register: nm_add_tenant_again_no_descr
+
+- name: Verify add_tenant_again_no_descr
+ assert:
+ that:
+ - nm_add_tenant_again_no_descr is not changed
+
+# QUERY ALL TENANTS
+- name: Query all tenants (normal mode)
+ cisco.aci.aci_rest: &tenant_query_all
+ 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/tn-[ansible_test].json
+ method: get
+ register: nm_query_all_tenants
+
+- name: Verify query_all_tenants
+ assert:
+ that:
+ - nm_query_all_tenants is not changed
+
+# QUERY A TENANT
+- name: Query our tenant
+ cisco.aci.aci_rest: &tenant_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") }}'
+ path: /api/mo/uni/tn-[ansible_test].json
+ method: get
+ register: nm_query_tenant
+
+- name: Verify query_tenant
+ assert:
+ that:
+ - nm_query_tenant is not changed
+
+# REMOVE TENANT
+- name: Remove tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant
+
+- name: Remove tenant again (normal mode)
+ cisco.aci.aci_rest: *tenant_absent
+ register: nm_remove_tenant_again
+
+- name: Verify remove_tenant
+ assert:
+ that:
+ - nm_remove_tenant is changed
+ - nm_remove_tenant_again is not changed
+
+# QUERY NON-EXISTING TENANT
+- name: Query non-existing tenant (normal mode)
+ cisco.aci.aci_rest: *tenant_query
+ register: nm_query_non_tenant
+
+- name: Verify query_non_tenant
+ assert:
+ that:
+ - nm_query_non_tenant is not changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml
new file mode 100644
index 000000000..e5c0ce185
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client/tasks/main.yml
@@ -0,0 +1,160 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_snmp_client_group if it already exists
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
+
+# ADD snmp policy
+- name: Add snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ admin_state: enabled
+ state: present
+
+# ADD snmp client group
+- name: Add snmp client group
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ mgmt_epg: oob-default
+ state: present
+
+# ADD snmp client
+- name: Add snmp client
+ aci_snmp_client:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ address: 10.20.30.0/24
+ client_name: snmp_client_name
+ state: present
+ register: add_snmp_client
+
+- name: Verify that ansible_snmp_client has been created with correct attributes
+ assert:
+ that:
+ - add_snmp_client.current.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]"
+ - add_snmp_client.current.0.snmpClientP.attributes.addr == "10.20.30.0/24"
+ - add_snmp_client.current.0.snmpClientP.attributes.name == "snmp_client_name"
+ - add_snmp_client.current.0.snmpClientP.attributes.annotation == 'orchestrator:ansible'
+
+# ADD snmp client again to check idempotency
+- name: Add snmp client again
+ aci_snmp_client:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ address: 10.20.30.0/24
+ client_name: snmp_client_name
+ state: present
+ register: add_snmp_client_again
+
+- name: Verify that add_snmp_client_group_again stays the same
+ assert:
+ that:
+ - add_snmp_client_again is not changed
+
+# MODIFY snmp client
+- name: Update snmp client
+ aci_snmp_client:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ address: 10.20.30.0/24
+ client_name: new_snmp_client_name
+ state: present
+ register: update_snmp_client
+
+- name: Verify that ansible_snmp_client_group has been updated with correct attributes
+ assert:
+ that:
+ - update_snmp_client is changed
+ - update_snmp_client.current.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]"
+ - update_snmp_client.current.0.snmpClientP.attributes.addr == "10.20.30.0/24"
+ - update_snmp_client.current.0.snmpClientP.attributes.name == "new_snmp_client_name"
+
+# QUERY snmp client
+- name: Query snmp client
+ aci_snmp_client:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ address: 10.20.30.0/24
+ state: query
+ register: query_snmp_client
+
+- name: Verify the attributes under query_snmp_client
+ assert:
+ that:
+ - query_snmp_client is not changed
+ - query_snmp_client.current.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]"
+ - query_snmp_client.current.0.snmpClientP.attributes.addr == "10.20.30.0/24"
+ - query_snmp_client.current.0.snmpClientP.attributes.name == "new_snmp_client_name"
+
+- name: Query all snmp client
+ aci_snmp_client:
+ <<: *aci_info
+ state: query
+ register: query_snmp_client_all
+
+- name: Verify query_snmp_client_all
+ assert:
+ that:
+ - query_snmp_client_all is not changed
+
+# DELETE snmp client group
+- name: Remove the snmp client
+ aci_snmp_client:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ address: 10.20.30.0/24
+ state: absent
+ register: remove_snmp_client
+
+- name: Verify remove_snmp_client
+ assert:
+ that:
+ - remove_snmp_client is changed
+ - remove_snmp_client.previous.0.snmpClientP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group/client-[10.20.30.0/24]"
+ - remove_snmp_client.previous.0.snmpClientP.attributes.addr == "10.20.30.0/24"
+
+# DELETE snmp policy
+- name: Remove the snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
+
+# DELETE snmp client group
+- name: Remove the snmp client group
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_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_snmp_client_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/tasks/main.yml
new file mode 100644
index 000000000..f54a7841a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_client_group/tasks/main.yml
@@ -0,0 +1,162 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_snmp_client_group if it already exists
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
+
+# ADD snmp policy
+- name: Add snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ admin_state: enabled
+ state: present
+
+# ADD snmp client group
+- name: Add snmp client group
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ mgmt_epg: oob-default
+ description: client group descr
+ state: present
+ register: add_snmp_client_group
+
+- name: Add snmp client group on default mgmt_epg
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group_no_epg
+ description: client group descr
+ state: present
+ register: add_snmp_client_group_no_epg
+
+- name: Verify that ansible_snmp_client_group has been created with correct attributes
+ assert:
+ that:
+ - add_snmp_client_group.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group"
+ - add_snmp_client_group.current.0.snmpClientGrpP.attributes.name == "ansible_snmp_client_group"
+ - add_snmp_client_group.current.0.snmpClientGrpP.attributes.descr == "client group descr"
+ - add_snmp_client_group.current.0.snmpClientGrpP.attributes.annotation == 'orchestrator:ansible'
+
+- name: Verify that ansible_snmp_client_group_no_epg has been created with correct attributes
+ assert:
+ that:
+ - add_snmp_client_group_no_epg.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group_no_epg"
+ - add_snmp_client_group_no_epg.current.0.snmpClientGrpP.attributes.name == "ansible_snmp_client_group_no_epg"
+ - add_snmp_client_group_no_epg.current.0.snmpClientGrpP.attributes.descr == "client group descr"
+
+- name: Verify that children of ansible_snmp_client_group have been created with correct values
+ assert:
+ that:
+ - add_snmp_client_group.current.0.snmpClientGrpP.children.0.snmpRsEpg.attributes.tDn == "uni/tn-mgmt/mgmtp-default/oob-default"
+
+# ADD snmp client group again to check idempotency
+- name: Add snmp client group again
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ mgmt_epg: oob-default
+ description: client group descr
+ state: present
+ register: add_snmp_client_group_again
+
+- name: Verify that add_snmp_client_group_again stays the same
+ assert:
+ that:
+ - add_snmp_client_group_again is not changed
+
+# MODIFY snmp client group
+- name: Update snmp client group
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ mgmt_epg: oob-default
+ description: new client group descr
+ state: present
+ register: update_snmp_client_group
+
+- name: Verify that ansible_snmp_client_group has been updated with correct attributes
+ assert:
+ that:
+ - update_snmp_client_group is changed
+ - update_snmp_client_group.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group"
+ - update_snmp_client_group.current.0.snmpClientGrpP.attributes.name == "ansible_snmp_client_group"
+ - update_snmp_client_group.current.0.snmpClientGrpP.attributes.descr == "new client group descr"
+
+# QUERY snmp client group
+- name: Query snmp client group
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ state: query
+ register: query_snmp_client_group
+
+- name: Verify the attributes under query_snmp_client_group
+ assert:
+ that:
+ - query_snmp_client_group is not changed
+ - query_snmp_client_group.current.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group"
+ - query_snmp_client_group.current.0.snmpClientGrpP.attributes.name == "ansible_snmp_client_group"
+ - query_snmp_client_group.current.0.snmpClientGrpP.attributes.descr == "new client group descr"
+
+- name: Query all snmp client groups
+ aci_snmp_client_group:
+ <<: *aci_info
+ state: query
+ register: query_snmp_client_group_all
+
+- name: Verify query_snmp_client_group_all
+ assert:
+ that:
+ - query_snmp_client_group_all is not changed
+
+# DELETE snmp client group
+- name: Remove the snmp client group
+ aci_snmp_client_group:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ client_group: ansible_snmp_client_group
+ state: absent
+ register: remove_snmp_client_group
+
+- name: Verify remove_snmp_client_group
+ assert:
+ that:
+ - remove_snmp_client_group is changed
+ - remove_snmp_client_group.previous.0.snmpClientGrpP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/clgrp-ansible_snmp_client_group"
+ - remove_snmp_client_group.previous.0.snmpClientGrpP.attributes.name == "ansible_snmp_client_group"
+
+# DELETE snmp policy
+- name: Remove the snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_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_snmp_community_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/tasks/main.yml
new file mode 100644
index 000000000..570476d37
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_community_policy/tasks/main.yml
@@ -0,0 +1,136 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_snmp_policy if it already exists
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
+
+# ADD snmp policy
+- name: Add snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ admin_state: enabled
+ state: present
+
+# ADD snmp community
+- name: Add snmp community
+ aci_snmp_community_policy:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ community: ansible_snmp_community
+ description: community description
+ register: add_snmp_community
+
+- name: Verify that ansible_snmp_community has been created with correct attributes
+ assert:
+ that:
+ - add_snmp_community.current.0.snmpCommunityP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/community-ansible_snmp_community"
+ - add_snmp_community.current.0.snmpCommunityP.attributes.name == "ansible_snmp_community"
+ - add_snmp_community.current.0.snmpCommunityP.attributes.descr == "community description"
+ - add_snmp_community.current.0.snmpCommunityP.attributes.annotation == 'orchestrator:ansible'
+
+# ADD snmp community again to check idempotency
+- name: Add snmp client group again
+ aci_snmp_community_policy:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ community: ansible_snmp_community
+ description: community description
+ register: add_snmp_community_again
+
+- name: Verify that add_snmp_community_again stays the same
+ assert:
+ that:
+ - add_snmp_community_again is not changed
+
+# MODIFY snmp client community
+- name: Update snmp community
+ aci_snmp_community_policy:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ community: ansible_snmp_community
+ description: new community description
+ register: update_snmp_community
+
+- name: Verify that ansible_snmp_community has been updated with correct attributes
+ assert:
+ that:
+ - update_snmp_community is changed
+ - update_snmp_community.current.0.snmpCommunityP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/community-ansible_snmp_community"
+ - update_snmp_community.current.0.snmpCommunityP.attributes.name == "ansible_snmp_community"
+ - update_snmp_community.current.0.snmpCommunityP.attributes.descr == "new community description"
+
+# QUERY snmp community
+- name: Query snmp community
+ aci_snmp_community_policy:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ community: ansible_snmp_community
+ state: query
+ register: query_snmp_community
+
+- name: Verify the attributes under query_snmp_client_group
+ assert:
+ that:
+ - query_snmp_community is not changed
+ - query_snmp_community.current.0.snmpCommunityP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/community-ansible_snmp_community"
+ - query_snmp_community.current.0.snmpCommunityP.attributes.name == "ansible_snmp_community"
+ - query_snmp_community.current.0.snmpCommunityP.attributes.descr == "new community description"
+
+- name: Query all snmp communities
+ aci_snmp_community_policy:
+ <<: *aci_info
+ state: query
+ register: query_snmp_community_all
+
+- name: Verify query_snmp_community_all
+ assert:
+ that:
+ - query_snmp_community_all is not changed
+
+# DELETE snmp community
+- name: Remove the snmp community
+ aci_snmp_community_policy:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ community: ansible_snmp_community
+ state: absent
+ register: remove_snmp_community
+
+- name: Verify remove_snmp_community
+ assert:
+ that:
+ - remove_snmp_community is changed
+ - remove_snmp_community.current == []
+ - remove_snmp_community.previous.0.snmpCommunityP.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy/community-ansible_snmp_community"
+ - remove_snmp_community.previous.0.snmpCommunityP.attributes.name == "ansible_snmp_community"
+
+# DELETE snmp policy
+- name: Remove the snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_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_snmp_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/tasks/main.yml
new file mode 100644
index 000000000..823ea8f30
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_policy/tasks/main.yml
@@ -0,0 +1,135 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_snmp_policy if it already exists
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
+
+# ADD snmp policy
+- name: Add snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ admin_state: enabled
+ contact: snmp contact
+ location: snmp location
+ description: policy description
+ state: present
+ register: add_snmp_policy
+
+- name: Verify that ansible_snmp_policy has been created with correct attributes
+ assert:
+ that:
+ - add_snmp_policy.current.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy"
+ - add_snmp_policy.current.0.snmpPol.attributes.name == "ansible_snmp_policy"
+ - add_snmp_policy.current.0.snmpPol.attributes.contact == "snmp contact"
+ - add_snmp_policy.current.0.snmpPol.attributes.loc == "snmp location"
+ - add_snmp_policy.current.0.snmpPol.attributes.adminSt == "enabled"
+ - add_snmp_policy.current.0.snmpPol.attributes.descr == "policy description"
+ - add_snmp_policy.current.0.snmpPol.attributes.annotation == 'orchestrator:ansible'
+
+# ADD snmp policy again to check idempotency
+- name: Add snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ admin_state: enabled
+ contact: snmp contact
+ location: snmp location
+ description: policy description
+ state: present
+ register: add_snmp_policy_again
+
+- name: Verify that ansible_snmp_policy stays the same
+ assert:
+ that:
+ - add_snmp_policy_again is not changed
+
+# MODIFY snmp policy
+- name: Update snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ admin_state: disabled
+ contact: new snmp contact
+ location: new snmp location
+ description: new policy description
+ state: present
+ register: update_snmp_policy
+
+- name: Verify that ansible_snmp_policy has been updated with correct attributes
+ assert:
+ that:
+ - update_snmp_policy.current.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy"
+ - update_snmp_policy.current.0.snmpPol.attributes.name == "ansible_snmp_policy"
+ - update_snmp_policy.current.0.snmpPol.attributes.contact == "new snmp contact"
+ - update_snmp_policy.current.0.snmpPol.attributes.loc == "new snmp location"
+ - update_snmp_policy.current.0.snmpPol.attributes.adminSt == "disabled"
+ - update_snmp_policy.current.0.snmpPol.attributes.descr == "new policy description"
+
+# QUERY snmp policy
+- name: Query snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: query
+ register: query_snmp_policy
+
+- name: Verify the attributes under query_snmp_policy
+ assert:
+ that:
+ - query_snmp_policy is not changed
+ - query_snmp_policy.current.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy"
+ - query_snmp_policy.current.0.snmpPol.attributes.name == "ansible_snmp_policy"
+ - query_snmp_policy.current.0.snmpPol.attributes.contact == "new snmp contact"
+ - query_snmp_policy.current.0.snmpPol.attributes.loc == "new snmp location"
+ - query_snmp_policy.current.0.snmpPol.attributes.adminSt == "disabled"
+ - query_snmp_policy.current.0.snmpPol.attributes.descr == "new policy description"
+
+- name: Query all snmp policies
+ aci_snmp_policy:
+ <<: *aci_info
+ state: query
+ register: query_snmp_policy_all
+
+- name: Verify query_snmp_policy_all
+ assert:
+ that:
+ - query_snmp_policy_all is not changed
+
+# DELETE snmp policy
+- name: Remove the snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
+ register: remove_snmp_policy
+
+- name: Verify remove_snmp_policy
+ assert:
+ that:
+ - remove_snmp_policy is changed
+ - remove_snmp_policy.previous.0.snmpPol.attributes.dn == "uni/fabric/snmppol-ansible_snmp_policy"
+ - remove_snmp_policy.previous.0.snmpPol.attributes.name == "ansible_snmp_policy"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..1b2608189
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_snmp_user/tasks/main.yml
@@ -0,0 +1,111 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_snmp_policy if it already exists
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ state: absent
+
+# ADD snmp policy
+- name: Add snmp policy
+ aci_snmp_policy:
+ <<: *aci_info
+ name: ansible_snmp_policy
+ admin_state: enabled
+ state: present
+
+# ADD snmp user
+- name: Add snmp user
+ aci_snmp_user:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ name: ansible_snmp_user
+ auth_type: hmac-sha1-96
+ auth_key: "auth-test-key"
+ privacy_type: aes-128
+ privacy_key: "priv-test-key"
+ state: present
+ register: add_snmp_user
+
+- name: Verify that ansible_snmp_community has been created with correct attributes
+ 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:
+ <<: *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:
+ that:
+ - query_snmp_user is not changed
+ - 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:
+ <<: *aci_info
+ state: query
+ register: query_snmp_user_all
+
+- name: Verify query_snmp_user_all
+ assert:
+ that:
+ - query_snmp_user_all is not changed
+
+# DELETE snmp user
+- name: Remove the snmp user
+ aci_snmp_user:
+ <<: *aci_info
+ policy: ansible_snmp_policy
+ name: ansible_snmp_user
+ state: absent
+ register: remove_snmp_user
+
+- name: Verify remove_snmp_user
+ 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"
+
+# DELETE snmp policy
+- name: Remove the snmp policy
+ 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/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..180848e28
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml
@@ -0,0 +1,391 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Bruno Calogero <bcalogero@cisco.com>
+# Copyright: (c) 2021, Cindy <cizhao@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
+ - name: Ensure static path to epg is deleted for test kick off
+ cisco.aci.aci_static_binding_to_epg: &aci_static_binding_to_epg_absent
+ <<: *aci_info
+ tenant: ansible_test
+ ap: anstest
+ epg: anstest
+ interface_type: switch_port
+ pod: 1
+ leafs: 101
+ interface: '1/7'
+ state: absent
+
+ - name: Ensure static path to epg is deleted
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_absent
+ interface_type: fex_port_channel
+ extpaths: 1011
+
+ - name: Ensure static path to epg is deleted
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_absent
+ interface_type: fex_vpc
+ interface: 'ansible_test'
+ leafs:
+ - 101
+ - 102
+ extpaths:
+ - 103
+ - 104
+
+ - 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 ap exists
+ cisco.aci.aci_ap: &aci_ap_present
+ <<: *aci_tenant_present
+ ap: anstest
+ register: ap_present
+
+ - name: Ensure epg exists
+ cisco.aci.aci_epg: &aci_epg_present
+ <<: *aci_ap_present
+ epg: anstest
+ register: epg_present
+
+ - name: Bind static-binding to epg - check mode works
+ cisco.aci.aci_static_binding_to_epg: &aci_static_binding_to_epg_present
+ <<: *aci_epg_present
+ encap_id: 222
+ deploy_immediacy: lazy
+ interface_mode: trunk
+ interface_type: switch_port
+ pod: 1
+ leafs: 101
+ interface: '1/7'
+ check_mode: true
+ register: provide_present_check_mode
+
+ - name: Bind static-binding to epg - provide works (creation w/o check-mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ ignore_errors: true
+ register: provide_present
+
+ - name: Bind static-binding to epg - switch port with multiple leafs
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ leafs:
+ - 101
+ - 102
+ ignore_errors: true
+ register: nm_multiple_leafs
+
+ - name: Bind static-binding to epg - three leafs
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ leafs:
+ - 101
+ - 102
+ - 103
+ ignore_errors: true
+ register: nm_multiple_leafs
+
+ - name: Bind static-binding to epg - primary_encap_id works
+ cisco.aci.aci_static_binding_to_epg: &primary_encap_id_present
+ <<: *aci_static_binding_to_epg_present
+ primary_encap_id: 50
+ register: primary_ecap_id_present
+
+ - name: Bind contract to epg - primary_encap_id invalid
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ primary_encap_id: invalid-vlan
+ ignore_errors: true
+ register: primary_encap_id_invalid
+
+ - name: Bind contract to epg - idempotency works again
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ register: idempotent_present
+
+ - name: Bind contract to epg - update description (check mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ description: Binding description
+ check_mode: true
+ register: description_cm
+
+ - name: Bind contract to epg - update description (run mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ description: Binding description
+ register: description
+
+ - name: Bind contract to epg - update description (check mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ description: Binding description
+ register: idempotent_description_cm
+
+ - name: Bind contract to epg - update description (run mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ description: Binding description
+ register: idempotent_description
+
+ - name: Missing required param - failure message works
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_tenant_present
+ ignore_errors: true
+ register: missing_required_present
+
+ - name: Present assertions
+ assert:
+ that:
+ - provide_present_check_mode is changed
+ - provide_present_check_mode.sent.fvRsPathAtt.attributes.encap == 'vlan-222'
+ - provide_present_check_mode.sent.fvRsPathAtt.attributes.instrImedcy == 'lazy'
+ - provide_present_check_mode.sent.fvRsPathAtt.attributes.mode == 'regular'
+ - provide_present_check_mode.sent.fvRsPathAtt.attributes.tDn == 'topology/pod-1/paths-101/pathep-[eth1/7]'
+ - provide_present is changed
+ - provide_present.sent == provide_present_check_mode.sent
+ - provide_present.current.0.fvRsPathAtt.attributes.annotation == 'orchestrator:ansible'
+ - provide_present.previous == []
+ - primary_ecap_id_present is changed
+ - primary_ecap_id_present.sent.fvRsPathAtt.attributes.primaryEncap == 'vlan-50'
+ - description_cm is changed
+ - description is changed
+ - idempotent_description_cm is not changed
+ - idempotent_description is not changed
+ - missing_required_present is failed
+ - 'missing_required_present.msg == "state is present but all of the following are missing: ap, encap_id, epg, interface, leafs, pod_id"'
+ - missing_required_present is failed
+ - primary_encap_id_invalid is failed
+
+ - name: Query specific binding
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ state: query
+ register: query_static_binding
+
+ - name: Query all bindings
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_tenant_present
+ state: query
+ register: query_all
+
+ - name: Query assertions
+ assert:
+ that:
+ - query_static_binding is not changed
+ - query_static_binding.current != []
+ - '"uni/tn-ansible_test/ap-anstest/epg-anstest/rspathAtt-[topology/pod-1/paths-101/pathep-[eth1/7]]" in query_static_binding.url'
+ - query_all is not changed
+ - '"uni/tn-ansible_test.json" in query_all.url'
+
+ # Testing when primary_encap_id = unknown
+ - name: Bind static-binding to epg - unknown primary_encap_id
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ primary_encap_id: 'unknown'
+ register: primary_ecap_id_unknown
+
+ - name: Bind static-binding to epg - omit primary_encap_id
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ primary_encap_id: "{{ item['primary_encap'] | default(omit) }}"
+ register: primary_ecap_id_omit
+
+ - name: Bind static-binding to epg - out of range primary_encap_id
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ primary_encap_id: 4098
+ ignore_errors: true
+ register: primary_ecap_id_range
+
+ - name: Bind static-binding to epg - out of range encap_id
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ encap_id: 4098
+ ignore_errors: true
+ register: encap_id_range
+
+ - name: primary_ecap_id assertions
+ assert:
+ that:
+ - primary_ecap_id_unknown is changed
+ - primary_ecap_id_unknown.sent.fvRsPathAtt.attributes.primaryEncap == 'unknown'
+ - primary_ecap_id_omit is not changed
+ - primary_ecap_id_omit.sent == {}
+ - primary_ecap_id_range is not changed
+ - primary_ecap_id_range.msg == 'Valid VLAN assignments are from 1 to 4096 or unknown.'
+ - encap_id_range.msg == 'Valid VLAN assignments are from 1 to 4096'
+
+ - name: Bind static-binding to epg - interface type fex_port_channel (check_mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_port_channel
+ extpaths: 1011
+ check_mode: true
+ register: cm_fex_port_channel
+
+ - name: Bind static-binding to epg - interface type fex_port_channel (normal mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_port_channel
+ extpaths: 1011
+ register: nm_fex_port_channel
+
+ - name: Bind static-binding to epg - interface type fex_vpc - incorrect extpaths (normal mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_vpc
+ extpaths:
+ - 1012
+ ignore_errors: true
+
+ - name: Bind static-binding to epg - interface type fex_vpc (normal mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_vpc
+ leafs:
+ - 101
+ - 102
+ interface: 'ansible_test'
+ extpaths:
+ - 103
+ - 104
+ register: nm_fex_vpc
+
+ - name: Bind static-binding to epg - fex_vpc with one extpaths (normal mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_vpc
+ leafs:
+ - 101
+ - 102
+ interface: 'ansible_test'
+ extpaths:
+ - 103
+ ignore_errors: true
+ register: fex_vpc_one_extpaths
+
+ - name: Bind static-binding to epg - fex_vpc with three extpaths (normal mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_vpc
+ leafs:
+ - 101
+ - 102
+ interface: 'ansible_test'
+ extpaths:
+ - 103
+ - 104
+ - 105
+ ignore_errors: true
+ 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:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_port_channel
+ extpaths:
+ - 101
+ - 102
+ check_mode: true
+ ignore_errors: true
+ register: cm_multiple_extpaths
+
+ - name: Bind static-binding to epg - fex_port_channel with multiple extpaths (normal mode)
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_present
+ interface_type: fex_port_channel
+ extpaths:
+ - 101
+ - 102
+ ignore_errors: true
+ register: nm_multiple_extpaths
+
+ - name: Verify interface type and extpaths
+ assert:
+ that:
+ - cm_fex_port_channel is changed
+ - nm_fex_port_channel is changed
+ - cm_fex_port_channel.previous == nm_fex_port_channel.previous == []
+ - cm_fex_port_channel.proposed.fvRsPathAtt.attributes.dn == 'uni/tn-ansible_test/ap-anstest/epg-anstest/rspathAtt-[topology/pod-1/paths-101/extpaths-1011/pathep-[1/7]]'
+ - nm_fex_port_channel.current.0.fvRsPathAtt.attributes.dn == 'uni/tn-ansible_test/ap-anstest/epg-anstest/rspathAtt-[topology/pod-1/paths-101/extpaths-1011/pathep-[1/7]]'
+ - nm_fex_vpc is changed
+ - nm_fex_vpc.previous == []
+ - nm_fex_vpc.current.0.fvRsPathAtt.attributes.dn == 'uni/tn-ansible_test/ap-anstest/epg-anstest/rspathAtt-[topology/pod-1/protpaths-101-102/extprotpaths-103-104/pathep-[ansible_test]]'
+
+ - name: Delete provide binding - deletion works
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ state: absent
+ register: provide_absent
+
+ - name: Delete provide binding - idempotency works
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *primary_encap_id_present
+ state: absent
+ register: provide_absent_idempotent
+
+ - name: Missing param - failure message works
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_tenant_present
+ state: absent
+ ignore_errors: true
+ register: missing_param_absent
+
+ - name: Absent assertions
+ assert:
+ that:
+ - provide_absent is changed
+ - provide_absent.previous.0.fvRsPathAtt is defined
+ - provide_absent_idempotent is not changed
+ - provide_absent_idempotent.previous == []
+ - missing_param_absent is failed
+ - missing_param_absent is failed
+ - 'missing_param_absent.msg == "state is absent but all of the following are missing: ap, epg, interface, leafs, pod_id"'
+
+ - name: Cleanup binding
+ cisco.aci.aci_static_binding_to_epg:
+ <<: *aci_static_binding_to_epg_absent
+
+ - name: Cleanup epg
+ cisco.aci.aci_epg:
+ <<: *aci_epg_present
+ state: absent
+
+ - name: Cleanup ap
+ cisco.aci.aci_ap:
+ <<: *aci_ap_present
+ state: absent
+
+ - name: Cleanup tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml
new file mode 100644
index 000000000..ce1553a45
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_static_node_mgmt_address/tasks/main.yml
@@ -0,0 +1,322 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: Remove node mgmt in_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband
+ encap: vlan-1
+ bd: bd1
+ state: absent
+
+ - name: Remove node mgmt out_of_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband
+ state: absent
+
+ # Add operations
+ - name: Add node mgmt in_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband
+ encap: vlan-1
+ bd: bd1
+ state: present
+
+ - name: Add node mgmt out_of_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband
+ state: present
+
+ - name: Add ipv4 address to mgmt interface in band in check mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ pod_id: 1
+ type: in_band
+ node_id: 110
+ ipv4_address: "3.1.1.2/24"
+ ipv4_gw: "3.1.1.1"
+ state: present
+ check_mode: true
+ register: cm_add_inb
+
+ - name: Add ipv4 address to mgmt interface out of band in check mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ pod_id: 1
+ type: out_of_band
+ node_id: 110
+ ipv4_address: '3.1.1.3/24'
+ ipv4_gw: "3.1.1.1"
+ state: present
+ check_mode: true
+ register: cm_add_oob
+
+ - name: Add ipv4 address to mgmt interface in band in normal mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ pod_id: 1
+ type: in_band
+ node_id: 110
+ ipv4_address: "3.1.1.2/24"
+ ipv4_gw: "3.1.1.1"
+ state: present
+ register: nm_add_inb
+
+ - name: Add ipv4 address to mgmt interface out of band in normal mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ pod_id: 1
+ type: out_of_band
+ node_id: 110
+ ipv4_address: "3.1.1.3/24"
+ ipv4_gw: "3.1.1.1"
+ state: present
+ register: nm_add_oob
+
+ - name: Add ipv4 address to mgmt interface in band in normal mode again
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ pod_id: 1
+ type: in_band
+ node_id: 110
+ ipv4_address: "3.1.1.2/24"
+ ipv4_gw: "3.1.1.1"
+ state: present
+ register: nm_add_inb_again
+
+ - name: Add ipv4 address to mgmt interface out of band in normal mode again
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ pod_id: 1
+ type: out_of_band
+ node_id: 110
+ ipv4_address: "3.1.1.3/24"
+ ipv4_gw: "3.1.1.1"
+ state: present
+ register: nm_add_oob_again
+
+ - name: Add another ipv4 address to mgmt interface in band in normal mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ pod_id: 1
+ type: in_band
+ node_id: 111
+ ipv4_address: "2.1.1.4/24"
+ ipv4_gw: "2.1.1.1"
+ state: present
+ register: nm_add_inb_2
+
+ - name: Add another ipv4 address to mgmt interface out of band in normal mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ pod_id: 1
+ type: out_of_band
+ node_id: 111
+ ipv4_address: "4.1.1.3/24"
+ ipv4_gw: "4.1.1.1"
+ state: present
+ register: nm_add_oob_2
+
+ - name: Verify add operations
+ assert:
+ that:
+ - cm_add_inb is changed
+ - cm_add_inb.sent.mgmtRsInBStNode.attributes.addr == '3.1.1.2/24'
+ - cm_add_oob is changed
+ - cm_add_oob.sent.mgmtRsOoBStNode.attributes.addr == '3.1.1.3/24'
+ - nm_add_inb is changed
+ - nm_add_inb.current.0.mgmtRsInBStNode.attributes.addr == '3.1.1.2/24'
+ - nm_add_inb.current.0.mgmtRsInBStNode.attributes.annotation == 'orchestrator:ansible'
+ - nm_add_oob is changed
+ - nm_add_oob.current.0.mgmtRsOoBStNode.attributes.addr == '3.1.1.3/24'
+ - nm_add_inb_2 is changed
+ - nm_add_inb_2.current.0.mgmtRsInBStNode.attributes.addr == '2.1.1.4/24'
+ - nm_add_oob_2 is changed
+ - nm_add_oob_2.current.0.mgmtRsOoBStNode.attributes.addr == '4.1.1.3/24'
+ - nm_add_inb_again is not changed
+ - nm_add_oob_again is not changed
+
+ - name: Query ipv4 address to mgmt interface in band in normal mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ pod_id: 1
+ type: in_band
+ node_id: 110
+ ipv4_address: "3.1.1.2/24"
+ ipv4_gw: "3.1.1.1"
+ state: query
+ register: nm_query_inb
+
+ - name: Query ipv4 address to mgmt interface out_of_band in normal mode
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ pod_id: 1
+ type: out_of_band
+ node_id: 110
+ ipv4_address: "3.1.1.3/24"
+ ipv4_gw: "3.1.1.1"
+ state: query
+ register: nm_query_oob
+
+ - name: Query all addresses in epg in band
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ type: in_band
+ state: query
+ register: query_all_epg_inb
+
+ - name: Query all addresses in epg out of band
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ type: out_of_band
+ state: query
+ register: query_all_epg_oob
+
+ - name: Query all in band addresses
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ type: in_band
+ state: query
+ register: query_all_inb
+
+ - name: Query all out_of_band addresses
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ type: out_of_band
+ state: query
+ register: query_all_oob
+
+ - name: Verify query operations
+ assert:
+ that:
+ - nm_query_inb is not changed
+ - nm_query_oob is not changed
+ - nm_query_inb.current.0.mgmtRsInBStNode.attributes.addr == '3.1.1.2/24'
+ - nm_query_oob.current.0.mgmtRsOoBStNode.attributes.addr == '3.1.1.3/24'
+ - query_all_epg_inb.current.0.mgmtInB.attributes.dn == 'uni/tn-mgmt/mgmtp-default/inb-ansible-inband'
+ - query_all_epg_inb.current.0.mgmtInB.children | length == 2
+ - query_all_epg_oob.current.0.mgmtOoB.attributes.dn == 'uni/tn-mgmt/mgmtp-default/oob-ansible-outofband'
+ - query_all_epg_oob.current.0.mgmtOoB.children | length == 2
+ - query_all_inb.current.0.mgmtMgmtP.children.0.mgmtInB.children | length == 2
+ - query_all_oob.current.0.mgmtMgmtP.children.0.mgmtOoB.children | length == 2
+
+ - name: Remove ipv4 address to mgmt interface in-band
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ pod_id: 1
+ type: in_band
+ node_id: 111
+ ipv4_address: "2.1.1.4/24"
+ ipv4_gw: "2.1.1.1"
+ state: absent
+ register: remove_in_band
+
+ - name: Remove ipv4 address to mgmt interface out of band
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ pod_id: 1
+ type: out_of_band
+ node_id: 111
+ ipv4_address: "4.1.1.3/24"
+ ipv4_gw: "4.1.1.1"
+ state: absent
+ register: remove_out_of_band
+
+ - name: Remove ipv4 address to mgmt interface in-band again
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-inband
+ pod_id: 1
+ type: in_band
+ node_id: 111
+ ipv4_address: "2.1.1.4/24"
+ ipv4_gw: "2.1.1.1"
+ state: absent
+ register: remove_in_band_again
+
+ - name: Remove ipv4 address to mgmt interface out of band again
+ aci_static_node_mgmt_address:
+ <<: *aci_info
+ epg: ansible-outofband
+ pod_id: 1
+ type: out_of_band
+ node_id: 111
+ ipv4_address: "4.1.1.3/24"
+ ipv4_gw: "4.1.1.1"
+ state: absent
+ register: remove_out_of_band_again
+
+ - name: Verify remove operations
+ assert:
+ that:
+ - remove_in_band is changed
+ - remove_in_band.previous.0.mgmtRsInBStNode.attributes.addr == '2.1.1.4/24'
+ - remove_out_of_band is changed
+ - remove_out_of_band.previous.0.mgmtRsOoBStNode.attributes.addr == '4.1.1.3/24'
+ - remove_out_of_band_again is not changed
+ - remove_out_of_band_again.previous == []
+ - remove_in_band_again is not changed
+ - remove_in_band_again.previous == []
+
+ # Clean environment for other ci test cases
+ - name: Remove node mgmt in_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: in_band
+ epg: ansible-inband
+ encap: vlan-1
+ bd: bd1
+ state: absent
+
+ - name: Remove node mgmt out_of_band epg
+ aci_node_mgmt_epg:
+ <<: *aci_info
+ type: out_of_band
+ epg: ansible-outofband
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_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_switch_leaf_selector/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml
new file mode 100644
index 000000000..d57239e49
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml
@@ -0,0 +1,149 @@
+# Test code for the ACI modules
+# 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)
+
+- 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
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Deleting Switch Policy Leaf profile exists for kick off
+ cisco.aci.aci_switch_policy_leaf_profile:
+ 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") }}'
+ leaf_profile: sw_name_test
+ state: absent
+
+ - name: Ensuring Switch Policy Leaf profile exists for kick off
+ cisco.aci.aci_switch_policy_leaf_profile: &aci_switch_policy_leaf_profile_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
+ leaf_profile: sw_name_test
+ state: present
+ register: leaf_profile_present
+
+ # TODO: Ensure that leaf Policy Group Exists (module missing) (infra:AccPortGrp)
+
+ - name: Adding a switch policy leaf profile selector associated Node Block range (w/o policy group) - check mode works
+ cisco.aci.aci_switch_leaf_selector: &aci_switch_leaf_selector_present
+ <<: *aci_switch_policy_leaf_profile_present
+ leaf: leaf_selector_name
+ leaf_node_blk: node_blk_name
+ from: 1011
+ to: 1011
+ check_mode: true
+ register: sw_leaf_selec_check_mode_present
+
+ - name: Adding a switch policy leaf profile selector associated Node Block range (w/o policy group) - creation works
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_leaf_selector_present
+ register: sw_leaf_selec_present
+
+ - name: Adding a switch policy leaf profile selector associated Node Block range (w/o policy group) - idempotency works
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_leaf_selector_present
+ register: sw_leaf_selec_idempotent
+
+ - name: Adding a switch policy leaf profile selector associated Node Block range (w/ policy group) - update works
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_leaf_selector_present
+ policy_group: anstest_policygroupname
+ register: sw_leaf_selec_update
+
+ # TODO: also test for errors
+ - name: present assertions
+ assert:
+ that:
+ - sw_leaf_selec_check_mode_present is changed
+ - sw_leaf_selec_present is changed
+ - sw_leaf_selec_present.previous == []
+ - sw_leaf_selec_present.sent.infraLeafS.attributes.name == 'leaf_selector_name'
+ - sw_leaf_selec_present.sent.infraLeafS.children.0.infraNodeBlk.attributes.from_ == '1011'
+ - sw_leaf_selec_present.sent.infraLeafS.children.0.infraNodeBlk.attributes.to_ == '1011'
+ - sw_leaf_selec_present.sent.infraLeafS.children.0.infraNodeBlk.attributes.name == 'node_blk_name'
+ - sw_leaf_selec_present.current.0.infraLeafS.attributes.annotation == 'orchestrator:ansible'
+ - sw_leaf_selec_idempotent is not changed
+ - sw_leaf_selec_idempotent.sent == {}
+ - sw_leaf_selec_update is changed
+ - sw_leaf_selec_update.sent.infraLeafS.attributes == {}
+ - sw_leaf_selec_update.sent.infraLeafS.children.0.infraRsAccNodePGrp.attributes.tDn == 'uni/infra/funcprof/accnodepgrp-anstest_policygroupname'
+
+ - name: Query Specific switch policy leaf profile selector
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_policy_leaf_profile_present
+ leaf: leaf_selector_name # "{{ fake_var | default(omit) }}" ?
+ state: query
+ register: binding_query
+
+ - name: present assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query.current | length >= 1
+ - '"api/mo/uni/infra/nprof-sw_name_test/leaves-leaf_selector_name-typ-range.json" in binding_query.url'
+
+ - name: Remove binding of interface access port selector and Interface Policy Leaf Profile - check mode
+ cisco.aci.aci_switch_leaf_selector: &aci_switch_leaf_selector_absent
+ <<: *aci_switch_policy_leaf_profile_present
+ leaf: leaf_selector_name
+ state: absent
+ check_mode: true
+ register: sw_leaf_selec_check_mode_absent
+
+ - name: Remove switch policy leaf profile selector - delete works
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_leaf_selector_absent
+ register: sw_leaf_selec_absent
+
+ - name: Remove switch policy leaf profile selector - idempotency works
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_leaf_selector_absent
+ register: sw_leaf_selec_absent_idempotent
+
+ - name: Remove switch policy leaf profile selector - check mode
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_policy_leaf_profile_present
+ #access_port_selector: anstest_accessportselector
+ state: absent
+ ignore_errors: true
+ register: sw_leaf_selec_absent_missing_param
+
+ - name: absent assertions
+ assert:
+ that:
+ - sw_leaf_selec_check_mode_absent is changed
+ - sw_leaf_selec_check_mode_absent.previous != []
+ - sw_leaf_selec_absent is changed
+ - sw_leaf_selec_absent.previous == sw_leaf_selec_check_mode_absent.previous
+ - sw_leaf_selec_absent_idempotent is not changed
+ - sw_leaf_selec_absent_idempotent.previous == []
+ - sw_leaf_selec_absent_missing_param is failed
+ - 'sw_leaf_selec_absent_missing_param.msg == "state is absent but all of the following are missing: leaf"'
+
+
+ - name: Remove switch policy leaf profile selector - Clean up
+ cisco.aci.aci_switch_leaf_selector:
+ <<: *aci_switch_leaf_selector_absent
+ state: absent
+
+ - name: Deleting Switch Policy Leaf profile exists for kick off
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_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_switch_policy_leaf_profile/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 000000000..2bed3b67c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,219 @@
+# Test code for the ACI modules
+# 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)
+
+- 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
+ block: # block specifies execution of tasks within, based on conditions
+ # CLEAN ENVIRONMENT
+ - name: Remove leaf profile
+ cisco.aci.aci_switch_policy_leaf_profile: &aci_switch_policy_leaf_profile_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") }}'
+ leaf_profile: ansible_test
+ state: absent
+
+
+ # ADD LEAF PROFILE
+ - name: Add switch policy leaf profile (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile: &aci_switch_policy_leaf_profile_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") }}'
+ leaf_profile: ansible_test
+ state: present
+ check_mode: true
+ register: cm_add_switch_leaf_profile
+
+ - name: Add leaf profile (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_present
+ register: nm_add_switch_leaf_profile
+
+ - name: Add leaf profile again (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_present
+ check_mode: true
+ register: cm_add_switch_leaf_profile_again
+
+ - name: Add leaf profile again (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_present
+ register: nm_add_switch_leaf_profile_again
+
+ - name: Verify add_switch_leaf_profile
+ assert:
+ that:
+ - cm_add_switch_leaf_profile is changed
+ - nm_add_switch_leaf_profile is changed
+ - nm_add_switch_leaf_profile.current.0.infraNodeP.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_switch_leaf_profile_again is not changed
+ - nm_add_switch_leaf_profile_again is not changed
+
+
+ # CHANGE SWITCH LEAF PROFILE
+ - name: Change description of leaf profile (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ description: Ansible test leaf profile
+ check_mode: true
+ register: cm_add_switch_leaf_profile_descr
+
+ - name: Change description of leaf profile (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ description: Ansible test leaf profile
+ register: nm_add_switch_leaf_profile_descr
+
+ - name: Change description of leaf profile again (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ description: Ansible test leaf profile
+ check_mode: true
+ register: cm_add_switch_leaf_profile_descr_again
+
+ - name: Change description of leaf profile again (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_present
+ description: Ansible test leaf profile
+ register: nm_add_switch_leaf_profile_descr_again
+
+ - name: Verify add_switch_leaf_profile_descr
+ assert:
+ that:
+ - cm_add_switch_leaf_profile_descr is changed
+ - nm_add_switch_leaf_profile_descr is changed
+ - cm_add_switch_leaf_profile_descr_again is not changed
+ - nm_add_switch_leaf_profile_descr_again is not changed
+
+
+ # ADD LEAF PROFILE AGAIN
+ - name: Add leaf profile again with no description (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_present
+ check_mode: true
+ register: cm_add_switch_leaf_profile_again_no_descr
+
+ - name: Add leaf profile again with no description (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_present
+ register: nm_add_switch_leaf_profile_again_no_descr
+
+ - name: Verify add_switch_leaf_profile_again_no_descr
+ assert:
+ that:
+ - cm_add_switch_leaf_profile_again_no_descr is not changed
+ - nm_add_switch_leaf_profile_again_no_descr is not changed
+
+
+ # QUERY ALL LEAF PROFILES
+ - name: Query all profiles (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile: &aci_switch_policy_leaf_profile_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_switch_leaf_profiles
+
+ - name: Query all switch_leaf_profiles (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_query
+ register: nm_query_all_switch_leaf_profiles
+
+ - name: Verify query_all_switch_leaf_profiles
+ assert:
+ that:
+ - cm_query_all_switch_leaf_profiles is not changed
+ - nm_query_all_switch_leaf_profiles is not changed
+ # NOTE: Order of switch_leaf_profiles is not stable between calls
+ #- cm_query_all_switch_leaf_profiles == nm_query_all_switch_leaf_profiles
+
+
+ # QUERY A LEAF PROFILE
+ - name: Query our switch_leaf_profile
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_query
+ leaf_profile: ansible_test
+ check_mode: true
+ register: cm_query_switch_leaf_profile
+
+ - name: Query our switch_leaf_profile
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_query
+ leaf_profile: ansible_test
+ register: nm_query_switch_leaf_profile
+
+ - name: Verify query_switch_leaf_profile
+ assert:
+ that:
+ - cm_query_switch_leaf_profile is not changed
+ - nm_query_switch_leaf_profile is not changed
+ - cm_query_switch_leaf_profile == nm_query_switch_leaf_profile
+
+
+ # REMOVE LEAF PROFILE
+ - name: Remove switch_leaf_profile (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_absent
+ check_mode: true
+ register: cm_remove_switch_leaf_profile
+
+ - name: Remove switch_leaf_profile (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_absent
+ register: nm_remove_switch_leaf_profile
+
+ - name: Remove switch_leaf_profile again (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_absent
+ check_mode: true
+ register: cm_remove_switch_leaf_profile_again
+
+ - name: Remove switch_leaf_profile again (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile: *aci_switch_policy_leaf_profile_absent
+ register: nm_remove_switch_leaf_profile_again
+
+ - name: Verify remove_switch_leaf_profile
+ assert:
+ that:
+ - cm_remove_switch_leaf_profile is changed
+ - nm_remove_switch_leaf_profile is changed
+ - cm_remove_switch_leaf_profile_again is not changed
+ - nm_remove_switch_leaf_profile_again is not changed
+
+
+ # QUERY NON-EXISTING LEAF PROFILE
+ - name: Query non-existing switch_leaf_profile (check_mode)
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_query
+ leaf_profile: ansible_test
+ check_mode: true
+ register: cm_query_non_switch_leaf_profile
+
+ - name: Query non-existing switch_leaf_profile (normal mode)
+ cisco.aci.aci_switch_policy_leaf_profile:
+ <<: *aci_switch_policy_leaf_profile_query
+ leaf_profile: ansible_test
+ register: nm_query_non_switch_leaf_profile
+
+ # TODO: Implement more tests
+ - name: Verify query_non_switch_leaf_profile
+ assert:
+ that:
+ - cm_query_non_switch_leaf_profile is not changed
+ - nm_query_non_switch_leaf_profile is not changed
+ - cm_query_non_switch_leaf_profile == nm_query_non_switch_leaf_profile
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_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_switch_policy_vpc_protection_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml
new file mode 100644
index 000000000..c0ef39cfe
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml
@@ -0,0 +1,214 @@
+# Test code for the ACI modules
+# 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)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+# CLEAN ENVIRONMENT
+- name: Remove vpc protection group
+ cisco.aci.aci_switch_policy_vpc_protection_group: &aci_switch_policy_vpc_protection_group_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") }}'
+ protection_group: ansible_test
+ state: absent
+
+
+# ADD VPC PROTECTION GROUP
+- name: Add vpc protection group (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: &aci_switch_policy_vpc_protection_group_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") }}'
+ protection_group: ansible_test
+ protection_group_id: 6
+ switch_1_id: 3811
+ switch_2_id: 3812
+ state: present
+ check_mode: true
+ register: cm_add_vpc_prot_grp
+
+- name: Add vpc protection group (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_present
+ register: nm_add_vpc_prot_grp
+
+- name: Add vpc protection group again (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_present
+ check_mode: true
+ register: cm_add_vpc_prot_grp_again
+
+- name: Add vpc protection group again (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_present
+ register: nm_add_vpc_prot_grp_again
+
+- name: Verify add_vpc_prot_grp_again
+ assert:
+ that:
+ - cm_add_vpc_prot_grp is changed
+ - nm_add_vpc_prot_grp is changed
+ - nm_add_vpc_prot_grp.current.0.fabricExplicitGEp.attributes.annotation == 'orchestrator:ansible'
+ - cm_add_vpc_prot_grp_again is not changed
+ - nm_add_vpc_prot_grp_again is not changed
+
+
+# CHANGE VPC PROTECTION GROUP
+- name: Change vpc domain policy of vpc protection group (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_present
+ vpc_domain_policy: ansible_test_pol
+ check_mode: true
+ register: cm_add_vpc_prot_grp_pol
+
+- name: Change vpc domain policy of vpc protection group (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_present
+ vpc_domain_policy: ansible_test_pol
+ register: nm_add_vpc_prot_grp_pol
+
+- name: Change vpc domain policy of vpc protection group again (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_present
+ vpc_domain_policy: ansible_test_pol
+ check_mode: true
+ register: cm_add_vpc_prot_grp_pol_again
+
+- name: Change vpc domain policy of vpc protection group again (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_present
+ vpc_domain_policy: ansible_test_pol
+ register: nm_add_vpc_prot_grp_pol_again
+
+- name: Verify add_vpc_prot_grp_pol
+ assert:
+ that:
+ - cm_add_vpc_prot_grp_pol is changed
+ - nm_add_vpc_prot_grp_pol is changed
+ - cm_add_vpc_prot_grp_pol_again is not changed
+ - nm_add_vpc_prot_grp_pol_again is not changed
+
+
+# ADD FABRIC NODE AGAIN
+- name: Add vpc protection group again with no domain policy (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_present
+ check_mode: true
+ register: cm_add_vpc_prot_grp_again_no_pol
+
+- name: Add vpc protection group again with no domain policy (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_present
+ register: nm_add_vpc_prot_grp_again_no_pol
+
+- name: Verify add_vpc_prot_grp_again_no_pol
+ assert:
+ that:
+ - cm_add_vpc_prot_grp_again_no_pol is not changed
+ - nm_add_vpc_prot_grp_again_no_pol is not changed
+
+
+# QUERY ALL VPC PROTECTION GROUPS
+- name: Query vpc protection groups (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: &aci_switch_policy_vpc_protection_group_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_vpc_prot_grps
+
+- name: Query all vpc protection groups (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_query
+ register: nm_query_all_vpc_prot_grps
+
+- name: Verify query_all_vpc_prot_grps
+ assert:
+ that:
+ - cm_query_all_vpc_prot_grps is not changed
+ - nm_query_all_vpc_prot_grps is not changed
+ - cm_query_all_vpc_prot_grps == nm_query_all_vpc_prot_grps
+
+
+# QUERY A VPC PROTECTION GROUP
+- name: Query our vpc protection group
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_query
+ protection_group: ansible_test # might need node_id too
+ check_mode: true
+ register: cm_query_vpc_prot_grp
+
+- name: Query our vpc protection group
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_query
+ protection_group: ansible_test
+ register: nm_query_vpc_prot_grp
+
+- name: Verify query_vpc_prot_grp
+ assert:
+ that:
+ - cm_query_vpc_prot_grp is not changed
+ - nm_query_vpc_prot_grp is not changed
+ - cm_query_vpc_prot_grp == nm_query_vpc_prot_grp
+
+
+# REMOVE FABRIC NODE
+- name: Remove vpc protection group (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_absent
+ check_mode: true
+ register: cm_remove_vpc_prot_grp
+
+- name: Remove vpc protection group (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_absent
+ register: nm_remove_vpc_prot_grp
+
+- name: Remove vpc protection group again (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_absent
+ check_mode: true
+ register: cm_remove_vpc_prot_grp_again
+
+- name: Remove vpc protection group again (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group: *aci_switch_policy_vpc_protection_group_absent
+ register: nm_remove_vpc_prot_grp_again
+
+- name: Verify remove_vpc_prot_grp
+ assert:
+ that:
+ - cm_remove_vpc_prot_grp is changed
+ - nm_remove_vpc_prot_grp is changed
+ - cm_remove_vpc_prot_grp_again is not changed
+ - nm_remove_vpc_prot_grp_again is not changed
+
+
+# QUERY NON-EXISTING LEAF PROFILE
+- name: Query non-existing vpc protection group (check_mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_query
+ protection_group: ansible_test
+ check_mode: true
+ register: cm_query_non_vpc_prot_grp
+
+- name: Query non-existing vpc protection group (normal mode)
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ <<: *aci_switch_policy_vpc_protection_group_query
+ protection_group: ansible_test
+ register: nm_query_non_vpc_prot_grp
+
+- name: Verify query_non_vpc_prot_grp
+ assert:
+ that:
+ - cm_query_non_vpc_prot_grp is not changed
+ - nm_query_non_vpc_prot_grp is not changed
+ - cm_query_non_vpc_prot_grp == nm_query_non_vpc_prot_grp
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_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_syslog_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/tasks/main.yml
new file mode 100644
index 000000000..f80ca35d2
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_group/tasks/main.yml
@@ -0,0 +1,245 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_syslog_group if it already exists
+ cisco.aci.aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ state: absent
+
+# ADD syslog group
+- name: Add syslog group (version >= 4)
+ cisco.aci.aci_syslog_group: &aci_syslog_present
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: enabled
+ format: aci
+ local_file_logging: enabled
+ local_file_log_severity: warnings
+ console_logging: enabled
+ console_log_severity: critical
+ include_ms: true
+ include_time_zone: true
+ state: present
+ register: add_syslog_group
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Add syslog group (version < 4)
+ cisco.aci.aci_syslog_group: &aci_syslog_present_32
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: enabled
+ format: aci
+ local_file_logging: enabled
+ local_file_log_severity: warnings
+ console_logging: enabled
+ console_log_severity: critical
+ include_ms: true
+ state: present
+ register: add_syslog_group_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+- name: Verify that ansible_syslog_group has been created with correct attributes (version > 4)
+ assert:
+ that:
+ - add_syslog_group.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group"
+ - add_syslog_group.current.0.syslogGroup.attributes.name == "ansible_syslog_group"
+ - add_syslog_group.current.0.syslogGroup.attributes.format == "aci"
+ - add_syslog_group.current.0.syslogGroup.attributes.includeMilliSeconds == "yes"
+ - add_syslog_group.current.0.syslogGroup.attributes.includeTimeZone == "yes"
+ - add_syslog_group.current.0.syslogGroup.attributes.annotation == 'orchestrator:ansible'
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Verify that ansible_syslog_group has been created with correct attributes (version < 4)
+ assert:
+ that:
+ - add_syslog_group_32.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group"
+ - add_syslog_group_32.current.0.syslogGroup.attributes.name == "ansible_syslog_group"
+ - add_syslog_group_32.current.0.syslogGroup.attributes.format == "aci"
+ - add_syslog_group_32.current.0.syslogGroup.attributes.includeMilliSeconds == "yes"
+ - add_syslog_group_32.current.0.syslogGroup.attributes.annotation == 'orchestrator:ansible'
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+- name: Verify that ansible_syslog_group children have correct attributes (version >= 4)
+ assert:
+ that:
+ - add_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "enabled"
+ - add_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "critical"
+ - add_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled"
+ - add_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "warnings"
+ - add_syslog_group.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "enabled"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Verify that ansible_syslog_group children have correct attributes (version < 4)
+ assert:
+ that:
+ - add_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "enabled"
+ - add_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "critical"
+ - add_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled"
+ - add_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "warnings"
+ - add_syslog_group_32.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "enabled"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+# ADD syslog group again to check idempotency
+- name: Add syslog group again (version >= 4)
+ cisco.aci.aci_syslog_group:
+ <<: *aci_syslog_present
+ register: add_syslog_group_again
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Add syslog group again (version < 4)
+ cisco.aci.aci_syslog_group:
+ <<: *aci_syslog_present_32
+ register: add_syslog_group_again_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+- name: Verify that ansible_syslog_group stays the same (version >= 4)
+ assert:
+ that:
+ - add_syslog_group_again is not changed
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Verify that ansible_syslog_group stays the same (version < 4)
+ assert:
+ that:
+ - add_syslog_group_again_32 is not changed
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+# MODIFY syslog group
+- name: Update syslog group (version >= 4)
+ cisco.aci.aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: disabled
+ format: nxos
+ local_file_logging: enabled
+ local_file_log_severity: debugging
+ console_logging: disabled
+ console_log_severity: emergencies
+ include_ms: false
+ include_time_zone: false
+ state: present
+ register: update_syslog_group
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Update syslog group (version < 4)
+ cisco.aci.aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: disabled
+ format: nxos
+ local_file_logging: enabled
+ local_file_log_severity: debugging
+ console_logging: disabled
+ console_log_severity: emergencies
+ include_ms: false
+ state: present
+ register: update_syslog_group_32
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+- name: Verify that ansible_syslog_group has been updated with correct attributes (version >= 4)
+ assert:
+ that:
+ - update_syslog_group.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group"
+ - update_syslog_group.current.0.syslogGroup.attributes.name == "ansible_syslog_group"
+ - update_syslog_group.current.0.syslogGroup.attributes.format == "nxos"
+ - update_syslog_group.current.0.syslogGroup.attributes.includeMilliSeconds == "no"
+ - update_syslog_group.current.0.syslogGroup.attributes.includeTimeZone == "no"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Verify that ansible_syslog_group has been updated with correct attributes (version < 4)
+ assert:
+ that:
+ - update_syslog_group_32.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group"
+ - update_syslog_group_32.current.0.syslogGroup.attributes.name == "ansible_syslog_group"
+ - update_syslog_group_32.current.0.syslogGroup.attributes.format == "nxos"
+ - update_syslog_group_32.current.0.syslogGroup.attributes.includeMilliSeconds == "no"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+- name: Verify that ansible_syslog_group children have correct attributes (version >= 4)
+ assert:
+ that:
+ - update_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "disabled"
+ - update_syslog_group.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "emergencies"
+ - update_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled"
+ - update_syslog_group.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "debugging"
+ - update_syslog_group.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "disabled"
+ when: version.current.0.topSystem.attributes.version is version('4', '>=')
+
+- name: Verify that ansible_syslog_group children have correct attributes (version < 4)
+ assert:
+ that:
+ - update_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.adminState == "disabled"
+ - update_syslog_group_32.current.0.syslogGroup.children.0.syslogConsole.attributes.severity == "emergencies"
+ - update_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.adminState == "enabled"
+ - update_syslog_group_32.current.0.syslogGroup.children.1.syslogFile.attributes.severity == "debugging"
+ - update_syslog_group_32.current.0.syslogGroup.children.2.syslogProf.attributes.adminState == "disabled"
+ when: version.current.0.topSystem.attributes.version is version('4', '<')
+
+# QUERY syslog group
+- name: Query the syslog group
+ cisco.aci.aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ state: query
+ register: query_syslog_group
+
+- name: Verify the attributes under query_syslog_group
+ assert:
+ that:
+ - query_syslog_group is not changed
+ - query_syslog_group.current.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group"
+ - query_syslog_group.current.0.syslogGroup.attributes.name == "ansible_syslog_group"
+
+- name: Query all syslog groups
+ cisco.aci.aci_syslog_group:
+ <<: *aci_info
+ state: query
+ register: query_syslog_group_all
+
+- name: Verify query_syslog_group_all
+ assert:
+ that:
+ - query_syslog_group_all is not changed
+
+# DELETE syslog group
+- name: Remove the syslog group
+ cisco.aci.aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ state: absent
+ register: remove_syslog_group
+
+- name: Verify remove_syslog_group
+ assert:
+ that:
+ - remove_syslog_group is changed
+ - remove_syslog_group.previous.0.syslogGroup.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group"
+ - remove_syslog_group.previous.0.syslogGroup.attributes.name == "ansible_syslog_group"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..0840aec20
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_remote_dest/tasks/main.yml
@@ -0,0 +1,197 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_syslog_src if it already exists
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ group: ansible_syslog_group
+ destination: "10.20.30.40"
+ state: absent
+
+# ADD syslog group
+- name: Add syslog group
+ aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: enabled
+ state: present
+
+# ADD syslog remote destination
+- name: Add syslog remote destination
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ group: ansible_syslog_group
+ destination: "10.20.30.40"
+ name: remote_destination_name
+ facility: local1
+ syslog_port: 5678
+ description: ansible syslog remote destination
+ mgmt_epg: oob-default
+ format: aci
+ admin_state: enabled
+ severity: warnings
+ state: present
+ register: add_syslog_remote_dest
+
+- name: Verify that ansible_syslog_src has been created with correct attributes
+ assert:
+ that:
+ - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group/rdst-10.20.30.40"
+ - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.name == "remote_destination_name"
+ - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.descr == "ansible syslog remote destination"
+ - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.format == "aci"
+ - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.forwardingFacility == "local1"
+ - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.host == "10.20.30.40"
+ - add_syslog_remote_dest.current.0.syslogRemoteDest.attributes.port == "5678"
+ - 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"
+
+# ADD syslog remote dest again to check idempotency
+- name: Add syslog remote dest
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ group: ansible_syslog_group
+ destination: "10.20.30.40"
+ name: remote_destination_name
+ facility: local1
+ syslog_port: 5678
+ description: ansible syslog remote destination
+ mgmt_epg: oob-default
+ format: aci
+ admin_state: enabled
+ severity: warnings
+ state: present
+ register: add_syslog_remote_dest_again
+
+- name: Verify that ansible_syslog_remote_dest stays the same
+ assert:
+ that:
+ - add_syslog_remote_dest_again is not changed
+
+# MODIFY syslog remote destination
+- name: Update the syslog remote destination
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ group: ansible_syslog_group
+ destination: "10.20.30.40"
+ name: new_remote_destination_name
+ facility: local7
+ syslog_port: 5679
+ description: new ansible syslog remote destination
+ mgmt_epg: oob-default
+ format: nxos
+ admin_state: disabled
+ severity: information
+ state: present
+ register: update_syslog_remote_dest
+
+- name: Verify that ansible_syslog_src has been updated with correct attributes
+ assert:
+ that:
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group/rdst-10.20.30.40"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.name == "new_remote_destination_name"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.descr == "new ansible syslog remote destination"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.format == "nxos"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.forwardingFacility == "local7"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.host == "10.20.30.40"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.port == "5679"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.adminState == "disabled"
+ - update_syslog_remote_dest.current.0.syslogRemoteDest.attributes.severity == "information"
+
+# QUERY syslog source
+- name: Query the syslog source
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ group: ansible_syslog_group
+ destination: "10.20.30.40"
+ state: query
+ register: query_syslog_remote_dest
+
+- name: Verify the attributes under query_syslog_src
+ assert:
+ that:
+ - query_syslog_remote_dest is not changed
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group/rdst-10.20.30.40"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.name == "new_remote_destination_name"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.descr == "new ansible syslog remote destination"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.format == "nxos"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.forwardingFacility == "local7"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.host == "10.20.30.40"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.port == "5679"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.adminState == "disabled"
+ - query_syslog_remote_dest.current.0.syslogRemoteDest.attributes.severity == "information"
+
+- name: Query all syslog remote destinations
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ state: query
+ register: query_syslog_remote_dest_all
+
+- name: Verify query_syslog_remote_dest_all
+ assert:
+ that:
+ - query_syslog_remote_dest_all is not changed
+
+# DELETE syslog remote destination
+- name: Remove the syslog remote dest
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ group: ansible_syslog_group
+ destination: "10.20.30.40"
+ state: absent
+ register: remove_syslog_remote_dest
+
+- name: Verify remove_syslog_remote_dest
+ assert:
+ that:
+ - remove_syslog_remote_dest is changed
+ - remove_syslog_remote_dest.current == []
+ - remove_syslog_remote_dest.previous.0.syslogRemoteDest.attributes.dn == "uni/fabric/slgroup-ansible_syslog_group/rdst-10.20.30.40"
+
+# DELETE syslog remote destination again to test idempotence
+- name: Remove the syslog remote dest again
+ aci_syslog_remote_dest:
+ <<: *aci_info
+ group: ansible_syslog_group
+ destination: "10.20.30.40"
+ state: absent
+ register: remove_syslog_remote_dest_again
+
+- name: Verify remove_syslog_remote_dest idempotence
+ assert:
+ that:
+ - remove_syslog_remote_dest_again is not changed
+
+# DELETE syslog group
+- name: Remove syslog group
+ aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: enabled
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..c237d17fe
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_syslog_source/tasks/main.yml
@@ -0,0 +1,168 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# CLEAN ENVIRONMENT
+- name: Remove ansible_syslog_src if it already exists
+ aci_syslog_source:
+ <<: *aci_info
+ name: ansible_syslog_src
+ state: absent
+
+# ADD syslog group
+- name: Add syslog group
+ aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: enabled
+ state: present
+
+# ADD syslog source
+- name: Add syslog source
+ aci_syslog_source:
+ <<: *aci_info
+ name: ansible_syslog_src
+ include:
+ - audit
+ - events
+ - faults
+ min_severity: errors
+ destination_group: ansible_syslog_group
+ state: present
+ register: add_syslog_src
+
+- name: Verify that ansible_syslog_src has been created with correct attributes
+ assert:
+ 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.minSev == "errors"
+ - add_syslog_src.current.0.syslogSrc.attributes.annotation == 'orchestrator:ansible'
+
+- name: Verify that ansible_syslog_src children have correct attributes
+ assert:
+ that:
+ - add_syslog_src.current.0.syslogSrc.children.0.syslogRsDestGroup.attributes.tDn == "uni/fabric/slgroup-ansible_syslog_group"
+
+# ADD syslog source again to check idempotency
+- name: Add syslog source
+ aci_syslog_source:
+ <<: *aci_info
+ name: ansible_syslog_src
+ include:
+ - audit
+ - events
+ - faults
+ min_severity: errors
+ destination_group: ansible_syslog_group
+ state: present
+ register: add_syslog_src_again
+
+- name: Verify that ansible_syslog_src stays the same
+ assert:
+ that:
+ - add_syslog_src_again is not changed
+
+# MODIFY syslog source
+- name: Update the syslog source
+ aci_syslog_source:
+ <<: *aci_info
+ name: ansible_syslog_src
+ include:
+ - faults
+ min_severity: information
+ destination_group: ansible_syslog_group
+ state: present
+ register: update_syslog_src
+
+- name: Verify that ansible_syslog_src has been updated with correct attributes
+ assert:
+ 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.minSev == "information"
+
+# QUERY syslog source
+- name: Query the syslog source
+ aci_syslog_source:
+ <<: *aci_info
+ name: ansible_syslog_src
+ state: query
+ register: query_syslog_src
+
+- name: Verify the attributes under query_syslog_src
+ assert:
+ that:
+ - 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.minSev == "information"
+
+- name: Query all syslog sources
+ aci_syslog_source:
+ <<: *aci_info
+ state: query
+ register: query_syslog_src_all
+
+- name: Verify query_syslog_src_all
+ assert:
+ that:
+ - query_syslog_src_all is not changed
+
+# DELETE syslog source
+- name: Remove the syslog source
+ aci_syslog_source:
+ <<: *aci_info
+ name: ansible_syslog_src
+ state: absent
+ register: remove_syslog_src
+
+- name: Verify remove_syslog_src
+ assert:
+ that:
+ - remove_syslog_src is changed
+ - remove_syslog_src.current == []
+ - remove_syslog_src.previous.0.syslogSrc.attributes.dn == "uni/fabric/moncommon/slsrc-ansible_syslog_src"
+ - remove_syslog_src.previous.0.syslogSrc.attributes.name == "ansible_syslog_src"
+
+# DELETE syslog source again to test idempotence
+- name: Remove the syslog source
+ aci_syslog_source:
+ <<: *aci_info
+ name: ansible_syslog_src
+ state: absent
+ register: remove_syslog_src_again
+
+- name: Verify remove_syslog_src idempotence
+ assert:
+ that:
+ - remove_syslog_src_again is not changed
+
+# DELETE syslog group
+- name: Remove syslog group
+ aci_syslog_group:
+ <<: *aci_info
+ name: ansible_syslog_group
+ admin_state: enabled
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_system/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_system/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system/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/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml
new file mode 100644
index 000000000..6be69c245
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml
@@ -0,0 +1,63 @@
+# Test code for the ACI modules
+# Copyright: (c) 2020, Lionel Hercot (@lhercot) <lhercot@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
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# QUERY OBJECTS
+- name: Query all controllers system information
+ aci_system:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+- name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.topSystem.attributes.id == "1"
+ - '"version" in query_all.current.0.topSystem.attributes'
+
+
+- name: Query a specific controller system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: query_controller
+
+- name: Verify query_controller
+ assert:
+ that:
+ - query_controller is not changed
+ - query_controller.current.0.topSystem.attributes.id == "1"
+ - '"version" in query_controller.current.0.topSystem.attributes'
+
+- name: Query non_existing controller
+ aci_system:
+ <<: *aci_info
+ id: 99
+ state: query
+ register: query_non_existing
+
+- name: Verify query_non_existing
+ assert:
+ that:
+ - query_non_existing is not changed
+ - query_non_existing.current == [] \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml
new file mode 100644
index 000000000..8a5bb5911
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml
@@ -0,0 +1,290 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+# CLEAN ENVIRONMENT
+- name: Remove taboo contract
+ cisco.aci.aci_taboo_contract: &taboo_contract_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
+ taboo_contract: taboo_contract_test
+ state: absent
+
+- name: Add 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") }}'
+ tenant: ansible_test
+ state: present
+
+
+# ADD TABOO CONTRACT
+- name: Add taboo contract (check_mode)
+ cisco.aci.aci_taboo_contract: &taboo_contract_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
+ taboo_contract: taboo_contract_test
+ state: present
+ check_mode: true
+ register: cm_add_taboo_contract
+
+- name: Add taboo contract (normal mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_present
+ register: nm_add_taboo_contract
+
+- name: Verify add_taboo_contract
+ assert:
+ that:
+ - cm_add_taboo_contract is changed
+ - nm_add_taboo_contract is changed
+ - cm_add_taboo_contract.sent.vzTaboo.attributes.name == nm_add_taboo_contract.sent.vzTaboo.attributes.name == 'taboo_contract_test'
+ - cm_add_taboo_contract.proposed.vzTaboo.attributes.name == nm_add_taboo_contract.proposed.vzTaboo.attributes.name == 'taboo_contract_test'
+ - cm_add_taboo_contract.previous == nm_add_taboo_contract.previous == []
+ # NOTE: We cannot fix this easily
+ - cm_add_taboo_contract.current == []
+ - nm_add_taboo_contract.current.0.vzTaboo.attributes.descr == ''
+ - nm_add_taboo_contract.current.0.vzTaboo.attributes.dn == 'uni/tn-ansible_test/taboo-taboo_contract_test'
+ - nm_add_taboo_contract.current.0.vzTaboo.attributes.name == 'taboo_contract_test'
+ - nm_add_taboo_contract.current.0.vzTaboo.attributes.annotation == 'orchestrator:ansible'
+
+- name: Add taboo_contract again (check_mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_present
+ check_mode: true
+ register: cm_add_taboo_contract_again
+
+- name: Add taboo contract again (normal mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_present
+ register: nm_add_taboo_contract_again
+
+- name: Verify add_taboo_contract_again
+ assert:
+ that:
+ - cm_add_taboo_contract_again is not changed
+ - nm_add_taboo_contract_again is not changed
+ - cm_add_taboo_contract_again.current == nm_add_taboo_contract_again.current == nm_add_taboo_contract.current
+
+
+# CHANGE TABOO CONTRACT
+- name: Change description of taboo contract (check_mode)
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_present
+ description: Ansible test taboo contract
+ check_mode: true
+ register: cm_add_taboo_contract_descr
+
+- name: Change description of taboo contract (normal mode)
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_present
+ description: Ansible test taboo contract
+ register: nm_add_taboo_contract_descr
+
+- name: Verify add_taboo_contract_descr
+ assert:
+ that:
+ - cm_add_taboo_contract_descr is changed
+ - nm_add_taboo_contract_descr is changed
+ - cm_add_taboo_contract_descr.sent.vzTaboo.attributes.descr == nm_add_taboo_contract_descr.sent.vzTaboo.attributes.descr == 'Ansible test taboo contract'
+ - cm_add_taboo_contract_descr.proposed.vzTaboo.attributes.descr == nm_add_taboo_contract_descr.proposed.vzTaboo.attributes.descr == 'Ansible test taboo contract'
+ - cm_add_taboo_contract_descr.proposed.vzTaboo.attributes.name == nm_add_taboo_contract_descr.proposed.vzTaboo.attributes.name == 'taboo_contract_test'
+ - cm_add_taboo_contract_descr.previous == nm_add_taboo_contract_descr.previous == cm_add_taboo_contract_descr.current == nm_add_taboo_contract.current
+ - nm_add_taboo_contract_descr.current.0.vzTaboo.attributes.descr == 'Ansible test taboo contract'
+ - nm_add_taboo_contract_descr.current.0.vzTaboo.attributes.dn == 'uni/tn-ansible_test/taboo-taboo_contract_test'
+ - nm_add_taboo_contract_descr.current.0.vzTaboo.attributes.name == 'taboo_contract_test'
+
+- name: Change description of taboo contract again (check_mode)
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_present
+ description: Ansible test taboo contract
+ check_mode: true
+ register: cm_add_taboo_contract_descr_again
+
+- name: Change description of taboo contract again (normal mode)
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_present
+ description: Ansible test taboo contract
+ register: nm_add_taboo_contract_descr_again
+
+- name: Verify add_taboo_contract_descr_again
+ assert:
+ that:
+ - cm_add_taboo_contract_descr_again is not changed
+ - nm_add_taboo_contract_descr_again is not changed
+ - cm_add_taboo_contract_descr_again.current == nm_add_taboo_contract_descr_again.current == nm_add_taboo_contract_descr.current
+
+
+# ADD TABOO CONTRACT AGAIN
+- name: Add taboo contract again with no description (check_mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_present
+ check_mode: true
+ register: cm_add_taboo_contract_again_no_descr
+
+- name: Add taboo contract again with no description (normal mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_present
+ register: nm_add_taboo_contract_again_no_descr
+
+- name: Verify add_taboo_contract_again_no_descr
+ assert:
+ that:
+ - cm_add_taboo_contract_again_no_descr is not changed
+ - nm_add_taboo_contract_again_no_descr is not changed
+ - cm_add_taboo_contract_again_no_descr.current == nm_add_taboo_contract_again_no_descr.current == nm_add_taboo_contract_descr.current
+
+
+# QUERY ALL TABOO CONTRACTS
+- name: Query all taboo contracts (check_mode)
+ cisco.aci.aci_taboo_contract: &taboo_contract_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_taboo_contracts
+
+- name: Query all taboo contracts (normal mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_query
+ register: nm_query_all_taboo_contracts
+
+- name: Verify query_all_taboo_contracts
+ assert:
+ that:
+ - cm_query_all_taboo_contracts is not changed
+ - nm_query_all_taboo_contracts is not changed
+ - cm_query_all_taboo_contracts == nm_query_all_taboo_contracts
+ - cm_query_all_taboo_contracts.current|length >= 1
+
+
+# QUERY A TABOO CONTRACT
+- name: Query our taboo contract
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_query
+ tenant: ansible_test
+ taboo_contract: taboo_contract_test
+ check_mode: true
+ register: cm_query_taboo_contract
+
+- name: Query our taboo contract
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_query
+ tenant: ansible_test
+ taboo_contract: taboo_contract_test
+ register: nm_query_taboo_contract
+
+- name: Verify query_taboo_contract
+ assert:
+ that:
+ - cm_query_taboo_contract is not changed
+ - nm_query_taboo_contract is not changed
+ - cm_query_taboo_contract == nm_query_taboo_contract
+ - nm_query_taboo_contract.current.0.vzTaboo.attributes.descr == 'Ansible test taboo contract'
+ - nm_query_taboo_contract.current.0.vzTaboo.attributes.dn == 'uni/tn-ansible_test/taboo-taboo_contract_test'
+ - nm_query_taboo_contract.current.0.vzTaboo.attributes.name == 'taboo_contract_test'
+
+
+# REMOVE TABOO CONTRACT
+- name: Remove taboo contract (check_mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_absent
+ check_mode: true
+ register: cm_remove_taboo_contract
+
+- name: Remove taboo contract (normal mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_absent
+ register: nm_remove_taboo_contract
+
+- name: Verify remove_taboo_contract
+ assert:
+ that:
+ - cm_remove_taboo_contract is changed
+ - nm_remove_taboo_contract is changed
+ - cm_remove_taboo_contract.current.0.vzTaboo.attributes.descr == cm_remove_taboo_contract.previous.0.vzTaboo.attributes.descr == nm_remove_taboo_contract.previous.0.vzTaboo.attributes.descr == 'Ansible test taboo contract'
+ - cm_remove_taboo_contract.current.0.vzTaboo.attributes.name == cm_remove_taboo_contract.previous.0.vzTaboo.attributes.name == nm_remove_taboo_contract.previous.0.vzTaboo.attributes.name == 'taboo_contract_test'
+ - cm_remove_taboo_contract.current.0.vzTaboo.attributes.dn == cm_remove_taboo_contract.previous.0.vzTaboo.attributes.dn == nm_remove_taboo_contract.previous.0.vzTaboo.attributes.dn == 'uni/tn-ansible_test/taboo-taboo_contract_test'
+ - nm_remove_taboo_contract.current == []
+
+- name: Remove taboo contract again (check_mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_absent
+ check_mode: true
+ register: cm_remove_taboo_contract_again
+
+- name: Remove taboo contract again (normal mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_absent
+ register: nm_remove_taboo_contract_again
+
+- name: Verify remove_taboo_contract_again
+ assert:
+ that:
+ - cm_remove_taboo_contract_again is not changed
+ - nm_remove_taboo_contract_again is not changed
+ - cm_remove_taboo_contract_again.proposed == nm_remove_taboo_contract_again.proposed == {}
+ - cm_remove_taboo_contract_again.sent == nm_remove_taboo_contract_again.sent == {}
+ - cm_remove_taboo_contract_again.previous == nm_remove_taboo_contract_again.previous == []
+ - cm_remove_taboo_contract_again.current == nm_remove_taboo_contract_again.current == []
+
+
+# QUERY NON-EXISTING TABOO CONTRACT
+- name: Query non-existing taboo contract (check_mode)
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_query
+ tenant: ansible_test
+ taboo_contract: taboo_contract_test
+ check_mode: true
+ register: cm_query_non_taboo_contract
+
+- name: Query non-existing taboo contract (normal mode)
+ cisco.aci.aci_taboo_contract:
+ <<: *taboo_contract_query
+ tenant: ansible_test
+ taboo_contract: taboo_contract_test
+ register: nm_query_non_taboo_contract
+
+# TODO: Implement more tests
+- name: Verify query_non_taboo_contract
+ assert:
+ that:
+ - cm_query_non_taboo_contract is not changed
+ - nm_query_non_taboo_contract is not changed
+ - cm_remove_taboo_contract_again.previous == nm_remove_taboo_contract_again.previous == []
+ - cm_remove_taboo_contract_again.current == nm_remove_taboo_contract_again.current == []
+
+
+# PROVOKE ERRORS
+- name: Error when required parameter is missing
+ cisco.aci.aci_taboo_contract:
+ 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") }}'
+ state: present
+ ignore_errors: true
+ register: error_on_missing_required_param
+
+- name: Verify error_on_missing_required_param
+ assert:
+ that:
+ - error_on_missing_required_param is failed
+ - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: tenant, taboo_contract"'
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml
new file mode 100644
index 000000000..e5a13ba7b
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tag/tasks/main.yml
@@ -0,0 +1,424 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+# Copyright: (c) 2020, Shreyas Srish (@shrsr)
+
+# 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: Remove tenant to cleanup
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+
+- name: Add tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_info
+ tenant: ansible_test
+ state: present
+ register: query_result
+
+- name: Get DN
+ set_fact:
+ dn: "{{ query_result.current[0].fvTenant.attributes.dn }}"
+
+- name: Annotation Create tag (check_mode)
+ cisco.aci.aci_tag: &annotation_present
+ <<: *aci_info
+ tag_key: foo
+ tag_value: bar
+ tag_type: annotation
+ dn: "{{ dn }}"
+ state: present
+ check_mode: true
+ register: cm_annotation_create
+
+- name: Annotation Create tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *annotation_present
+ state: present
+ register: nm_annotation_create
+
+- name: Annotation tag created
+ assert:
+ that:
+ - cm_annotation_create is changed
+ - cm_annotation_create.proposed.tagAnnotation.attributes.value == "bar"
+ - nm_annotation_create is changed
+ - nm_annotation_create.current.0.tagAnnotation.attributes.key == "foo"
+ - nm_annotation_create.current.0.tagAnnotation.attributes.value == "bar"
+
+- name: Annotation Create tag again (check_mode)
+ cisco.aci.aci_tag:
+ <<: *annotation_present
+ state: present
+ check_mode: true
+ register: cm_annotation_create_again
+
+- name: Annotation Create tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *annotation_present
+ state: present
+ register: nm_annotation_create_again
+
+- name: Annotation tag create again
+ assert:
+ that:
+ - cm_annotation_create_again is not changed
+ - cm_annotation_create_again.current.0.tagAnnotation.attributes.key == "foo"
+ - cm_annotation_create_again.current.0.tagAnnotation.attributes.value == "bar"
+ - nm_annotation_create_again is not changed
+ - nm_annotation_create_again.current.0.tagAnnotation.attributes.key == "foo"
+ - nm_annotation_create_again.current.0.tagAnnotation.attributes.value == "bar"
+
+- name: Annotation Query tag
+ cisco.aci.aci_tag:
+ <<: *annotation_present
+ state: query
+ register: annotation_query_result
+
+- name: Annotation tag query verification
+ assert:
+ that:
+ - annotation_query_result is not changed
+ - annotation_query_result.current.0.tagAnnotation.attributes.key == "foo"
+ - annotation_query_result.current.0.tagAnnotation.attributes.value == "bar"
+
+- name: Annotation Query all tags
+ cisco.aci.aci_tag:
+ <<: *annotation_present
+ dn: "{{ fake_var | default(omit) }}"
+ tag_key: "{{ fake_var | default(omit) }}"
+ state: query
+ register: annotation_query_all
+
+- name: Annotation tag query verification
+ assert:
+ that:
+ - annotation_query_all is not changed
+
+- name: Annotation tag query verification (continued)
+ assert:
+ that:
+ - annotation_query_all.current.0.tagAnnotation.attributes.key == "foo"
+ - annotation_query_all.current.0.tagAnnotation.attributes.value == "bar"
+ when: query_cloud.current == [] # This condition will skip execution for cloud sites
+
+- name: Annotation Delete tag (check_mode)
+ cisco.aci.aci_tag: &annotation_absent
+ <<: *annotation_present
+ tag_value: "{{ fake_var | default(omit) }}"
+ state: absent
+ check_mode: true
+ register: cm_annotation_delete
+
+- name: Annotation Delete tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *annotation_absent
+ state: absent
+ register: nm_annotation_delete
+
+- name: Annotation tag deleted
+ assert:
+ that:
+ - cm_annotation_delete is changed
+ - nm_annotation_delete is changed
+ - cm_annotation_delete.proposed.tagAnnotation is not defined
+ - nm_annotation_delete.current.0.tagAnnotation is not defined
+ - cm_annotation_delete.previous.0.tagAnnotation.attributes.key == "foo"
+ - nm_annotation_delete.previous.0.tagAnnotation.attributes.key == "foo"
+ - cm_annotation_delete.previous.0.tagAnnotation.attributes.value == "bar"
+ - nm_annotation_delete.previous.0.tagAnnotation.attributes.value == "bar"
+
+- name: Annotation Delete tag again (check_mode)
+ cisco.aci.aci_tag:
+ <<: *annotation_absent
+ state: absent
+ check_mode: true
+ register: cm_annotation_delete_again
+
+- name: Annotation Delete tag again (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *annotation_absent
+ state: absent
+ register: nm_annotation_delete_again
+
+- name: Annotation tag deleted again
+ assert:
+ that:
+ - cm_annotation_delete_again is not changed
+ - nm_annotation_delete_again is not changed
+ - cm_annotation_delete_again.current.0.tagAnnotation is not defined
+ - nm_annotation_delete_again.current.0.tagAnnotation is not defined
+ - cm_annotation_delete_again.previous.0.tagAnnotation is not defined
+ - nm_annotation_delete_again.previous.0.tagAnnotation is not defined
+
+- name: Instance Create tag (check_mode)
+ cisco.aci.aci_tag: &instance_present
+ <<: *aci_info
+ tag_key: foo
+ tag_type: instance
+ dn: "{{ dn }}"
+ state: present
+ check_mode: true
+ register: cm_instance_create
+
+- name: Instance Create tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *instance_present
+ state: present
+ register: nm_instance_create
+
+- name: Instance tag created
+ assert:
+ that:
+ - cm_instance_create is changed
+ - nm_instance_create is changed
+ - nm_instance_create.current.0.tagInst.attributes.name == "foo"
+
+- name: Instance Create tag again (check_mode)
+ cisco.aci.aci_tag:
+ <<: *instance_present
+ state: present
+ check_mode: true
+ register: cm_instance_create_again
+
+- name: Instance Create tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *instance_present
+ state: present
+ register: nm_instance_create_again
+
+- name: Instance tag create again
+ assert:
+ that:
+ - cm_instance_create_again is not changed
+ - cm_instance_create_again.current.0.tagInst.attributes.name == "foo"
+ - nm_instance_create_again is not changed
+ - nm_instance_create_again.current.0.tagInst.attributes.name == "foo"
+
+- name: Instance Query tag
+ cisco.aci.aci_tag:
+ <<: *instance_present
+ state: query
+ register: instance_query_result
+
+- name: Instance tag query verification
+ assert:
+ that:
+ - instance_query_result is not changed
+ - instance_query_result.current.0.tagInst.attributes.name == "foo"
+
+- name: Instance Query all tags
+ cisco.aci.aci_tag:
+ <<: *instance_present
+ dn: "{{ fake_var | default(omit) }}"
+ tag_key: "{{ fake_var | default(omit) }}"
+ state: query
+ register: instance_query_all
+
+- name: Instance tag query verification
+ assert:
+ that:
+ - instance_query_all is not changed
+
+- name: Instance tag query verification (continued)
+ assert:
+ that:
+ - instance_query_all.current.0.tagInst.attributes.name == "foo"
+ when: query_cloud.current == [] # This condition will skip execution for cloud sites
+
+- name: Instance Delete tag (check_mode)
+ cisco.aci.aci_tag: &instance_absent
+ <<: *instance_present
+ tag_value: "{{ fake_var | default(omit) }}"
+ state: absent
+ check_mode: true
+ register: cm_instance_delete
+
+- name: Instance Delete tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *instance_absent
+ state: absent
+ register: nm_instance_delete
+
+- name: Instance tag deleted
+ assert:
+ that:
+ - cm_instance_delete is changed
+ - nm_instance_delete is changed
+ - cm_instance_delete.proposed.tagInst is not defined
+ - nm_instance_delete.current.0.tagInst is not defined
+ - cm_instance_delete.previous.0.tagInst.attributes.name == "foo"
+ - nm_instance_delete.previous.0.tagInst.attributes.name == "foo"
+
+- name: Instance Delete tag again (check_mode)
+ cisco.aci.aci_tag:
+ <<: *instance_absent
+ state: absent
+ check_mode: true
+ register: cm_instance_delete_again
+
+- name: Instance Delete tag again (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *instance_absent
+ state: absent
+ register: nm_instance_delete_again
+
+- name: Instance tag deleted again
+ assert:
+ that:
+ - cm_instance_delete_again is not changed
+ - nm_instance_delete_again is not changed
+ - cm_instance_delete_again.current.0.tagInst is not defined
+ - nm_instance_delete_again.current.0.tagInst is not defined
+ - cm_instance_delete_again.previous.0.tagInst is not defined
+ - nm_instance_delete_again.previous.0.tagInst is not defined
+
+- name: Tag Create tag (check_mode)
+ cisco.aci.aci_tag: &tag_present
+ <<: *aci_info
+ tag_key: foo
+ tag_value: bar
+ tag_type: tag
+ dn: "{{ dn }}"
+ state: present
+ check_mode: true
+ register: cm_tag_create
+
+- name: Tag Create tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *tag_present
+ state: present
+ register: nm_tag_create
+
+- name: Tag tag created
+ assert:
+ that:
+ - cm_tag_create is changed
+ - cm_tag_create.proposed.tagTag.attributes.value == "bar"
+ - nm_tag_create is changed
+ - nm_tag_create.current.0.tagTag.attributes.key == "foo"
+ - nm_tag_create.current.0.tagTag.attributes.value == "bar"
+
+- name: Tag Create tag again (check_mode)
+ cisco.aci.aci_tag:
+ <<: *tag_present
+ state: present
+ check_mode: true
+ register: cm_tag_create_again
+
+- name: Tag Create tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *tag_present
+ state: present
+ register: nm_tag_create_again
+
+- name: Tag tag create again
+ assert:
+ that:
+ - cm_tag_create_again is not changed
+ - cm_tag_create_again.current.0.tagTag.attributes.key == "foo"
+ - cm_tag_create_again.current.0.tagTag.attributes.value == "bar"
+ - nm_tag_create_again is not changed
+ - nm_tag_create_again.current.0.tagTag.attributes.key == "foo"
+ - nm_tag_create_again.current.0.tagTag.attributes.value == "bar"
+
+- name: Tag Query tag
+ cisco.aci.aci_tag:
+ <<: *tag_present
+ state: query
+ register: tag_query_result
+
+- name: Tag tag query verification
+ assert:
+ that:
+ - tag_query_result is not changed
+ - tag_query_result.current.0.tagTag.attributes.key == "foo"
+ - tag_query_result.current.0.tagTag.attributes.value == "bar"
+
+- name: Tag Query all tags
+ cisco.aci.aci_tag:
+ <<: *tag_present
+ dn: "{{ fake_var | default(omit) }}"
+ tag_key: "{{ fake_var | default(omit) }}"
+ state: query
+ register: tag_query_all
+
+- name: Tag tag query verification
+ assert:
+ that:
+ - tag_query_all is not changed
+
+- name: Tag tag query verification (continued)
+ assert:
+ that:
+ - tag_query_all.current.0.tagTag.attributes.key == "foo"
+ - tag_query_all.current.0.tagTag.attributes.value == "bar"
+ when: query_cloud.current == [] # This condition will skip execution for cloud sites
+
+- name: Tag Delete tag (check_mode)
+ cisco.aci.aci_tag: &tag_absent
+ <<: *tag_present
+ tag_value: "{{ fake_var | default(omit) }}"
+ state: absent
+ check_mode: true
+ register: cm_tag_delete
+
+- name: Tag Delete tag (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *tag_absent
+ state: absent
+ register: nm_tag_delete
+
+- name: Tag tag deleted
+ assert:
+ that:
+ - cm_tag_delete is changed
+ - nm_tag_delete is changed
+ - cm_tag_delete.proposed.tagTag is not defined
+ - nm_tag_delete.current.0.tagTag is not defined
+ - cm_tag_delete.previous.0.tagTag.attributes.key == "foo"
+ - nm_tag_delete.previous.0.tagTag.attributes.key == "foo"
+ - cm_tag_delete.previous.0.tagTag.attributes.value == "bar"
+ - nm_tag_delete.previous.0.tagTag.attributes.value == "bar"
+
+- name: Tag Delete tag again (check_mode)
+ cisco.aci.aci_tag:
+ <<: *tag_absent
+ state: absent
+ check_mode: true
+ register: cm_tag_delete_again
+
+- name: Tag Delete tag again (normal_mode)
+ cisco.aci.aci_tag:
+ <<: *tag_absent
+ state: absent
+ register: nm_tag_delete_again
+
+- name: Tag tag deleted again
+ assert:
+ that:
+ - cm_tag_delete_again is not changed
+ - nm_tag_delete_again is not changed
+ - cm_tag_delete_again.current.0.tagTag is not defined
+ - nm_tag_delete_again.current.0.tagTag is not defined
+ - cm_tag_delete_again.previous.0.tagTag is not defined
+ - nm_tag_delete_again.previous.0.tagTag is not defined
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/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/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml
new file mode 100644
index 000000000..f3eba556e
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml
@@ -0,0 +1,366 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+# Copyright: (c) 2020, Lionel Hercot (@lhercot) <lhercot@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: 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"
+
+# CLEAN ENVIRONMENT
+- name: Remove tenant
+ cisco.aci.aci_tenant: &tenant_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
+ state: absent
+
+
+# ADD TENANT
+- name: Add tenant (check_mode)
+ cisco.aci.aci_tenant: &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: '{{ aci_output_level | default("info") }}'
+ tenant: ansible_test
+ state: present
+ annotation: ansible_test
+ owner_key: ansible_key
+ owner_tag: ansible_tag
+ output_path: "{{ ansible_host }}_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')}}"
+
+- name: Add tenant (normal mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ output_path: "{{ ansible_host }}_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"
+ 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"
+ register: nm_add_tenant_again
+
+- name: Dump content of files
+ debug:
+ msg: "{{ lookup('file', ansible_host + '_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') }}"
+
+- name: Log file content verification for create object
+ assert:
+ that:
+ - fc_cm_add_tenant.0.fvTenant.attributes.name == 'ansible_test'
+ - fc_cm_add_tenant.0.fvTenant.attributes.dn == 'uni/tn-ansible_test'
+ - fc_nm_add_tenant.0.fvTenant.attributes.name == 'ansible_test'
+ - fc_nm_add_tenant.0.fvTenant.attributes.dn == 'uni/tn-ansible_test'
+ - fc_cm_add_tenant_again == ''
+ - fc_nm_add_tenant_again == ''
+
+- name: Verify add_tenant
+ assert:
+ that:
+ - cm_add_tenant is changed
+ - nm_add_tenant is changed
+ - cm_add_tenant_again is not changed
+ - nm_add_tenant_again is not changed
+ - nm_add_tenant.current[0].fvTenant.attributes.annotation == 'ansible_test'
+ - cm_add_tenant.proposed.fvTenant.attributes.annotation == 'ansible_test'
+ - nm_add_tenant.current[0].fvTenant.attributes.ownerKey == 'ansible_key'
+ - cm_add_tenant.proposed.fvTenant.attributes.ownerKey == 'ansible_key'
+ - 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:
+ <<: *tenant_present
+ description: Ansible test tenant
+ annotation: ansible_test_changed
+ owner_key: ansible_key_changed
+ owner_tag: ansible_tag_changed
+ output_path: "{{ ansible_host }}_cm_add_tenant_descr.json"
+ check_mode: true
+ register: cm_add_tenant_descr
+
+- name: Change description and annotation/owner_tag/owner_key of tenant (normal mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ description: Ansible test tenant
+ annotation: ansible_test_changed
+ owner_key: ansible_key_changed
+ owner_tag: ansible_tag_changed
+ output_path: "{{ ansible_host }}_nm_add_tenant_descr.json"
+ register: nm_add_tenant_descr
+
+- name: Change description and annotation/owner_tag/owner_key of tenant again (check_mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ description: Ansible test tenant
+ annotation: ansible_test_changed
+ owner_key: ansible_key_changed
+ owner_tag: ansible_tag_changed
+ output_path: "{{ ansible_host }}_cm_add_tenant_descr_again.json"
+ check_mode: true
+ register: cm_add_tenant_descr_again
+
+- name: Change description and annotation of tenant again (normal mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ description: Ansible test tenant
+ annotation: ansible_test_changed
+ owner_key: ansible_key_changed
+ owner_tag: ansible_tag_changed
+ output_path: "{{ ansible_host }}_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') }}"
+
+- name: Log file content verification for update object
+ assert:
+ that:
+ - fc_cm_add_tenant_descr.0.fvTenant.attributes.descr == 'Ansible test tenant'
+ - fc_nm_add_tenant_descr.0.fvTenant.attributes.descr == 'Ansible test tenant'
+ - fc_cm_add_tenant_descr_again == ''
+ - fc_nm_add_tenant_descr_again == ''
+
+- name: Verify add_tenant_descr
+ assert:
+ that:
+ - cm_add_tenant_descr is changed
+ - nm_add_tenant_descr is changed
+ - cm_add_tenant_descr_again is not changed
+ - nm_add_tenant_descr_again is not changed
+ - cm_add_tenant_descr.proposed.fvTenant.attributes.annotation == 'ansible_test_changed'
+ - nm_add_tenant_descr.current[0].fvTenant.attributes.annotation == 'ansible_test_changed'
+ - cm_add_tenant_descr_again.proposed.fvTenant.attributes.annotation == 'ansible_test_changed'
+ - nm_add_tenant_descr_again.current[0].fvTenant.attributes.annotation == 'ansible_test_changed'
+ - nm_add_tenant_descr.current[0].fvTenant.attributes.ownerKey == 'ansible_key_changed'
+ - cm_add_tenant_descr.proposed.fvTenant.attributes.ownerKey == 'ansible_key_changed'
+ - nm_add_tenant_descr_again.current[0].fvTenant.attributes.ownerKey == 'ansible_key_changed'
+ - cm_add_tenant_descr_again.proposed.fvTenant.attributes.ownerKey == 'ansible_key_changed'
+ - nm_add_tenant_descr.current[0].fvTenant.attributes.ownerTag == 'ansible_tag_changed'
+ - cm_add_tenant_descr.proposed.fvTenant.attributes.ownerTag == 'ansible_tag_changed'
+ - nm_add_tenant_descr_again.current[0].fvTenant.attributes.ownerTag == 'ansible_tag_changed'
+ - cm_add_tenant_descr_again.proposed.fvTenant.attributes.ownerTag == 'ansible_tag_changed'
+
+
+# ADD TENANT AGAIN
+- name: Add tenant again with no description (check_mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ annotation: ansible_test_changed
+ owner_key: ansible_key_changed
+ owner_tag: ansible_tag_changed
+ check_mode: true
+ register: cm_add_tenant_again_no_descr
+
+- name: Add tenant again with no description (normal mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ annotation: ansible_test_changed
+ owner_key: ansible_key_changed
+ owner_tag: ansible_tag_changed
+ register: nm_add_tenant_again_no_descr
+
+- name: Verify add_tenant_again_no_descr
+ assert:
+ that:
+ - cm_add_tenant_again_no_descr is not changed
+ - nm_add_tenant_again_no_descr is not changed
+
+
+# QUERY ALL TENANTS
+- name: Query all tenants (check_mode)
+ cisco.aci.aci_tenant: &tenant_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_tenants
+
+- name: Query all tenants (normal mode)
+ cisco.aci.aci_tenant: *tenant_query
+ register: nm_query_all_tenants
+
+- name: Verify query_all_tenants
+ assert:
+ that:
+ - cm_query_all_tenants is not changed
+ - nm_query_all_tenants is not changed
+ # NOTE: Order of tenants is not stable between calls
+ #- cm_query_all_tenants == nm_query_all_tenants
+
+
+# QUERY A TENANT
+- name: Query our tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_query
+ tenant: ansible_test
+ check_mode: true
+ register: cm_query_tenant
+
+- name: Query our tenant
+ cisco.aci.aci_tenant:
+ <<: *tenant_query
+ tenant: ansible_test
+ register: nm_query_tenant
+
+- name: Verify query_tenant
+ assert:
+ that:
+ - cm_query_tenant is not changed
+ - nm_query_tenant is not changed
+ - cm_query_tenant == nm_query_tenant
+ - cm_query_tenant.current[0].fvTenant.attributes.annotation == 'ansible_test_changed'
+ - nm_query_tenant.current[0].fvTenant.attributes.annotation == 'ansible_test_changed'
+ - nm_query_tenant.current[0].fvTenant.attributes.ownerKey == 'ansible_key_changed'
+ - cm_query_tenant.current[0].fvTenant.attributes.ownerKey == 'ansible_key_changed'
+ - nm_query_tenant.current[0].fvTenant.attributes.ownerTag == 'ansible_tag_changed'
+ - cm_query_tenant.current[0].fvTenant.attributes.ownerTag == 'ansible_tag_changed'
+
+
+- name: Update tenant with default annotation
+ cisco.aci.aci_tenant:
+ <<: *tenant_present
+ annotation: "{{ fake_var | default(omit) }}"
+ register: default_annotation
+
+- name: Assertion check for update tenant with default annotation
+ assert:
+ that:
+ - default_annotation is changed
+ - default_annotation.current.0.fvTenant.attributes.annotation == 'orchestrator:ansible'
+
+# REMOVE TENANT
+- name: Remove tenant (check_mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_absent
+ output_path: "{{ ansible_host }}_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"
+ 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"
+ 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"
+ 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') }}"
+
+- name: Log file content verification for delete object
+ assert:
+ that:
+ - fc_cm_remove_tenant.0.fvTenant.attributes.status == 'deleted'
+ - fc_cm_remove_tenant.0.fvTenant.attributes.dn == 'uni/tn-ansible_test'
+ - fc_nm_remove_tenant == [{}]
+ - fc_cm_remove_tenant_again == ''
+ - fc_nm_remove_tenant_again == ''
+
+- name: Verify remove_tenant
+ assert:
+ that:
+ - cm_remove_tenant is changed
+ - nm_remove_tenant is changed
+ - cm_remove_tenant_again is not changed
+ - nm_remove_tenant_again is not changed
+
+
+# QUERY NON-EXISTING TENANT
+- name: Query non-existing tenant (check_mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_query
+ tenant: ansible_test
+ check_mode: true
+ register: cm_query_non_tenant
+
+- name: Query non-existing tenant (normal mode)
+ cisco.aci.aci_tenant:
+ <<: *tenant_query
+ tenant: ansible_test
+ register: nm_query_non_tenant
+
+# TODO: Implement more tests
+- name: Verify query_non_tenant
+ assert:
+ that:
+ - cm_query_non_tenant is not changed
+ - nm_query_non_tenant is not changed
+ - cm_query_non_tenant == nm_query_non_tenant
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_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_tenant_span_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml
new file mode 100644
index 000000000..d7d807ad8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_dst_group/tasks/main.yml
@@ -0,0 +1,241 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Shreyas Srish (@shrsr)
+
+# 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: 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 == []
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_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_tenant_span_src_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml
new file mode 100644
index 000000000..9f83d0344
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group/tasks/main.yml
@@ -0,0 +1,184 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: 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: Add a new tenant
+ cisco.aci.aci_tenant: &aci_tenant
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: present
+
+ - name: Add new bd
+ cisco.aci.aci_bd: &aci_bd
+ <<: *aci_tenant
+ bd: anstest
+ register: bd_present
+
+ - name: Add a new source ap
+ cisco.aci.aci_ap:
+ <<: *aci_tenant
+ ap: ansible_source_ap
+
+ - name: Add a new dest ap
+ cisco.aci.aci_ap:
+ <<: *aci_tenant
+ ap: ansible_dest_ap
+
+ - name: Add a new dest epg
+ cisco.aci.aci_epg:
+ <<: *aci_bd
+ ap: ansible_dest_ap
+ epg: ansible_dest_epg
+
+ - name: Add a new source epg
+ cisco.aci.aci_epg:
+ <<: *aci_bd
+ ap: ansible_dest_ap
+ epg: ansible_source_epg
+
+ - name: Add span dest group
+ cisco.aci.aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_dest_group
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: "CS1"
+ destination_epg:
+ tenant: ansible_tenant
+ ap: ansible_dest_ap
+ epg: ansible_dest_epg
+ state: present
+
+ - name: Create a source group (check mode)
+ cisco.aci.aci_tenant_span_src_group: &aci_span
+ <<: *aci_tenant
+ name: ansible_span
+ description: ansible test description
+ dst_group: ansible_dest_group
+ check_mode: true
+ register: cm_create_with_dest
+
+ - name: Create a source group
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_span
+ register: nm_create_with_dest
+
+ - name: Create a source group again
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_span
+ register: nm_create_with_dest_again
+
+ - name: Create second source group
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_tenant
+ name: ansible_span_2
+ description: ansible test description
+ register: create_without_dest
+
+ - name: Change second source group
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_tenant
+ name: ansible_span_2
+ description: ansible test description 2
+ register: change_without_dest
+
+ - name: Verify create of source groups
+ ansible.builtin.assert:
+ that:
+ - cm_create_with_dest is changed
+ - nm_create_with_dest is changed
+ - nm_create_with_dest.current.0.spanSrcGrp.attributes.name == "ansible_span"
+ - nm_create_with_dest.current.0.spanSrcGrp.attributes.descr == "ansible test description"
+ - nm_create_with_dest.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "ansible_dest_group"
+ - nm_create_with_dest_again is not changed
+ - nm_create_with_dest_again.current.0.spanSrcGrp.attributes.name == "ansible_span"
+ - nm_create_with_dest_again.current.0.spanSrcGrp.attributes.descr == "ansible test description"
+ - nm_create_with_dest_again.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "ansible_dest_group"
+ - create_without_dest is changed
+ - create_without_dest.current.0.spanSrcGrp.attributes.name == "ansible_span_2"
+ - create_without_dest.current.0.spanSrcGrp.attributes.descr == "ansible test description"
+ - '"children" not in create_without_dest.current.0.spanSrcGrp'
+ - change_without_dest is changed
+ - change_without_dest.current.0.spanSrcGrp.attributes.name == "ansible_span_2"
+ - change_without_dest.current.0.spanSrcGrp.attributes.descr == "ansible test description 2"
+ - '"children" not in change_without_dest.current.0.spanSrcGrp'
+
+ - name: Query a source groups
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_span
+ state: query
+ register: query_one
+
+ - name: Query all source groups
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify queries to source groups
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current.0.spanSrcGrp.attributes.name == "ansible_span"
+ - query_one.current.0.spanSrcGrp.attributes.descr == "ansible test description"
+ - query_one.current.0.spanSrcGrp.children.0.spanSpanLbl.attributes.name == "ansible_dest_group"
+ - query_all is not changed
+ - query_all.current | length == 2
+
+ - name: Delete a source group
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_span
+ state: absent
+ register: delete
+
+ - name: Delete a source group again
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_span
+ state: absent
+ register: delete_again
+
+ - name: Verify delete of source group
+ ansible.builtin.assert:
+ that:
+ - delete is changed
+ - delete_again is not changed
+ - delete.current == []
+
+ - name: Remove the ansible_tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_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_tenant_span_src_group_src/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml
new file mode 100644
index 000000000..65b8722f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_src/tasks/main.yml
@@ -0,0 +1,204 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: 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: Add a new tenant
+ cisco.aci.aci_tenant: &aci_tenant
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: present
+
+ - name: Add new bd
+ cisco.aci.aci_bd: &aci_bd
+ <<: *aci_tenant
+ bd: anstest
+ register: bd_present
+
+ - name: Add a new source ap
+ cisco.aci.aci_ap:
+ <<: *aci_tenant
+ ap: ansible_source_ap
+
+ - name: Add a new dest ap
+ cisco.aci.aci_ap:
+ <<: *aci_tenant
+ ap: ansible_dest_ap
+
+ - name: Add a new dest epg
+ cisco.aci.aci_epg:
+ <<: *aci_bd
+ ap: ansible_dest_ap
+ epg: ansible_dest_epg
+
+ - name: Add a new source epg
+ cisco.aci.aci_epg:
+ <<: *aci_bd
+ ap: ansible_dest_ap
+ epg: ansible_source_epg
+
+ - name: Add span dest group
+ cisco.aci.aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_dest_group
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: "CS1"
+ destination_epg:
+ tenant: ansible_tenant
+ ap: ansible_dest_ap
+ epg: ansible_dest_epg
+ state: present
+
+ - name: Create a source group
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_tenant
+ name: ansible_span
+ description: ansible test description
+ dst_group: ansible_dest_group
+ register: nm_create_with_dest
+
+ - name: Create a ansible_source SPAN Source (check mode)
+ cisco.aci.aci_tenant_span_src_group_src: &aci_src
+ <<: *aci_tenant
+ name: ansible_source
+ description: ansible test description
+ direction: incoming
+ src_ap: ansible_source_ap
+ src_epg: ansible_source_epg
+ src_group: ansible_span
+ check_mode: true
+ register: cm_create_with_epg
+
+ - name: Create a ansible_source SPAN Source
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_src
+ register: nm_create_with_epg
+
+ - name: Create a ansible_source SPAN Source again
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_src
+ register: nm_create_with_epg_again
+
+ - name: Create second ansible_source SPAN Source
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_tenant
+ name: ansible_source_2
+ description: ansible test description 2
+ direction: outgoing
+ src_group: ansible_span
+ register: create_without_epg_direction_outgoing
+
+ - name: Change second ansible_source SPAN Source
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_tenant
+ name: ansible_source_2
+ description: ansible test description 3
+ direction: both
+ src_group: ansible_span
+ register: change_without_epg_direction_both
+
+ - name: Verify create and changes of sources
+ ansible.builtin.assert:
+ that:
+ - cm_create_with_epg is changed
+ - nm_create_with_epg is changed
+ - nm_create_with_epg.current.0.spanSrc.attributes.name == "ansible_source"
+ - nm_create_with_epg.current.0.spanSrc.attributes.descr == "ansible test description"
+ - nm_create_with_epg.current.0.spanSrc.attributes.dir == "in"
+ - nm_create_with_epg.current.0.spanSrc.children.0.spanRsSrcToEpg.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_source_ap/epg-ansible_source_epg"
+ - nm_create_with_epg_again is not changed
+ - nm_create_with_epg_again.current.0.spanSrc.attributes.name == "ansible_source"
+ - nm_create_with_epg_again.current.0.spanSrc.attributes.descr == "ansible test description"
+ - nm_create_with_epg_again.current.0.spanSrc.attributes.dir == "in"
+ - nm_create_with_epg_again.current.0.spanSrc.children.0.spanRsSrcToEpg.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_source_ap/epg-ansible_source_epg"
+ - create_without_epg_direction_outgoing is changed
+ - create_without_epg_direction_outgoing.current.0.spanSrc.attributes.name == "ansible_source_2"
+ - create_without_epg_direction_outgoing.current.0.spanSrc.attributes.descr == "ansible test description 2"
+ - create_without_epg_direction_outgoing.current.0.spanSrc.attributes.dir == "out"
+ - '"children" not in create_without_epg_direction_outgoing.current.0.spanSrc'
+ - change_without_epg_direction_both is changed
+ - change_without_epg_direction_both.current.0.spanSrc.attributes.name == "ansible_source_2"
+ - change_without_epg_direction_both.current.0.spanSrc.attributes.descr == "ansible test description 3"
+ - change_without_epg_direction_both.current.0.spanSrc.attributes.dir == "both"
+ - '"children" not in change_without_epg_direction_both.current.0.spanSrc'
+
+ - name: Query a ansible_source SPAN Source
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_src
+ state: query
+ register: query_one
+
+ - name: Query all ansible_source SPAN Sources
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify queries of ansible_source SPAN Sources
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current.0.spanSrc.attributes.name == "ansible_source"
+ - query_one.current.0.spanSrc.attributes.descr == "ansible test description"
+ - query_one.current.0.spanSrc.attributes.dir == "in"
+ - query_one.current.0.spanSrc.children.0.spanRsSrcToEpg.attributes.tDn == "uni/tn-ansible_tenant/ap-ansible_source_ap/epg-ansible_source_epg"
+ - query_all is not changed
+ - query_all.current | length == 2
+
+ - name: Delete a ansible_source SPAN Source
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_src
+ state: absent
+ register: delete
+
+ - name: Delete a ansible_source SPAN Source again
+ cisco.aci.aci_tenant_span_src_group_src:
+ <<: *aci_src
+ state: absent
+ register: delete_again
+
+ - name: Verify delete of ansible_source SPAN Source
+ ansible.builtin.assert:
+ that:
+ - delete is changed
+ - delete_again is not changed
+ - delete.current == []
+
+ - name: Remove the ansible_tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_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_tenant_span_src_group_to_dst_group/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml
new file mode 100644
index 000000000..e9dac612d
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant_span_src_group_to_dst_group/tasks/main.yml
@@ -0,0 +1,202 @@
+# Test code for the ACI modules
+# Copyright: (c) 2022, 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: 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: Add a new tenant
+ cisco.aci.aci_tenant: &aci_tenant
+ <<: *aci_info
+ tenant: ansible_tenant
+ state: present
+
+ - name: Add new bd
+ cisco.aci.aci_bd: &aci_bd
+ <<: *aci_tenant
+ bd: anstest
+ register: bd_present
+
+ - name: Add a new source ap
+ cisco.aci.aci_ap:
+ <<: *aci_tenant
+ ap: ansible_source_ap
+
+ - name: Add a new dest ap
+ cisco.aci.aci_ap:
+ <<: *aci_tenant
+ ap: ansible_dest_ap
+
+ - name: Add a new dest epg
+ cisco.aci.aci_epg:
+ <<: *aci_bd
+ ap: ansible_dest_ap
+ epg: ansible_dest_epg
+
+ - name: Add a new source epg
+ cisco.aci.aci_epg:
+ <<: *aci_bd
+ ap: ansible_dest_ap
+ epg: ansible_source_epg
+
+ - name: Add span dest group
+ cisco.aci.aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_dest_group
+ destination_ip: 10.0.0.1
+ source_ip: 10.0.2.1
+ tenant: ansible_tenant
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: "CS1"
+ destination_epg:
+ tenant: ansible_tenant
+ ap: ansible_dest_ap
+ epg: ansible_dest_epg
+ state: present
+
+ - name: Add span dest group
+ cisco.aci.aci_tenant_span_dst_group:
+ <<: *aci_info
+ destination_group: ansible_dest_group_2
+ destination_ip: 20.0.0.1
+ source_ip: 20.0.2.1
+ tenant: ansible_tenant
+ ttl: 2
+ mtu: 1500
+ flow_id: 1
+ dscp: "CS1"
+ destination_epg:
+ tenant: ansible_tenant
+ ap: ansible_dest_ap
+ epg: ansible_dest_epg
+ state: present
+
+ - name: Create a source group
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_tenant
+ name: ansible_span
+ description: ansible test description
+
+ - name: Create another source group
+ cisco.aci.aci_tenant_span_src_group:
+ <<: *aci_tenant
+ name: ansible_span_2
+ description: ansible test description
+
+ - name: Create a source group to destination (check mode)
+ cisco.aci.aci_tenant_span_src_group_to_dst_group: &aci_source_to_dest
+ <<: *aci_tenant
+ src_group: ansible_span
+ dst_group: ansible_dest_group
+ check_mode: true
+ register: cm_create
+
+ - name: Create a source group to destination
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_source_to_dest
+ register: nm_create
+
+ - name: Create a source group to destination again
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_source_to_dest
+ register: nm_create_again
+
+ - name: Create another source group to destination
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_tenant
+ src_group: ansible_span_2
+ dst_group: ansible_dest_group_2
+ register: nm_create_another
+
+ - name: Change a source group to destination (error not allowed)
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_source_to_dest
+ dst_group: ansible_dest_group_2
+ ignore_errors: true
+ register: error_change
+
+ - name: Verify create source groups to destination
+ ansible.builtin.assert:
+ that:
+ - cm_create is changed
+ - nm_create is changed
+ - nm_create.current.0.spanSpanLbl.attributes.name == "ansible_dest_group"
+ - nm_create_again is not changed
+ - nm_create_again.current.0.spanSpanLbl.attributes.name == "ansible_dest_group"
+ - nm_create_another is changed
+ - nm_create_another.current.0.spanSpanLbl.attributes.name == "ansible_dest_group_2"
+ - error_change is not changed
+ - 'error_change.msg == "APIC Error 105: Only one span destination is supported per session"'
+
+ - name: Query a a source group to destination
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_source_to_dest
+ state: query
+ register: query_one
+
+ - name: Query all a source group to destinations
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_info
+ state: query
+ register: query_all
+
+ - name: Verify queries of source group to destination
+ ansible.builtin.assert:
+ that:
+ - query_one is not changed
+ - query_one.current.0.spanSpanLbl.attributes.name == "ansible_dest_group"
+ - query_all is not changed
+ - query_all.current | length == 2
+
+ - name: Delete a source group to destination
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_source_to_dest
+ state: absent
+ register: delete
+
+ - name: Delete a source group to destination again
+ cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ <<: *aci_source_to_dest
+ state: absent
+ register: delete_again
+
+ - name: Verify delete of source group to destinations
+ ansible.builtin.assert:
+ that:
+ - delete is changed
+ - delete_again is not changed
+ - delete.current == []
+
+ - name: Remove the ansible_tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant
+ state: absent \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml
new file mode 100644
index 000000000..0469210f8
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml
@@ -0,0 +1,304 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# CLEAN ENVIRONMENT
+- name: Remove dynamic vlan pool
+ cisco.aci.aci_vlan_pool: &dynamic_vlan_pool_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") }}'
+ pool: anstest
+ pool_allocation_mode: dynamic
+ state: absent
+
+
+# ADD VLAN POOL
+- name: Add dynamic vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool: &dynamic_vlan_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") }}'
+ pool: anstest
+ pool_allocation_mode: dynamic
+ state: present
+ check_mode: true
+ register: cm_add_dynamic_vlan_pool
+
+- name: Add dynamic vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_present
+ register: nm_add_dynamic_vlan_pool
+
+- name: Verify add_dynamic_vlan_pool
+ assert:
+ that:
+ - cm_add_dynamic_vlan_pool is changed
+ - nm_add_dynamic_vlan_pool is changed
+ - cm_add_dynamic_vlan_pool.sent.fvnsVlanInstP.attributes.allocMode == nm_add_dynamic_vlan_pool.sent.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - cm_add_dynamic_vlan_pool.sent.fvnsVlanInstP.attributes.name == nm_add_dynamic_vlan_pool.sent.fvnsVlanInstP.attributes.name == 'anstest'
+ - cm_add_dynamic_vlan_pool.proposed.fvnsVlanInstP.attributes.allocMode == nm_add_dynamic_vlan_pool.proposed.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - cm_add_dynamic_vlan_pool.proposed.fvnsVlanInstP.attributes.name == nm_add_dynamic_vlan_pool.proposed.fvnsVlanInstP.attributes.name == 'anstest'
+ - cm_add_dynamic_vlan_pool.previous == nm_add_dynamic_vlan_pool.previous == []
+ # NOTE: We cannot fix this easily
+ - cm_add_dynamic_vlan_pool.current == []
+ - nm_add_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - nm_add_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.descr == ''
+ - nm_add_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-dynamic'
+ - nm_add_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.name == 'anstest'
+ - nm_add_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.annotation == 'orchestrator:ansible'
+
+- name: Add dynamic_vlan_pool again (check_mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_present
+ check_mode: true
+ register: cm_add_dynamic_vlan_pool_again
+
+- name: Add dynamic vlan pool again (normal mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_present
+ register: nm_add_dynamic_vlan_pool_again
+
+- name: Verify add_dynamic_vlan_pool_again
+ assert:
+ that:
+ - cm_add_dynamic_vlan_pool_again is not changed
+ - nm_add_dynamic_vlan_pool_again is not changed
+ - cm_add_dynamic_vlan_pool_again.current == nm_add_dynamic_vlan_pool_again.current == nm_add_dynamic_vlan_pool.current
+
+
+# CHANGE VLAN POOL
+- name: Change description of dynamic vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_present
+ description: Ansible test dynamic vlan pool
+ check_mode: true
+ register: cm_add_dynamic_vlan_pool_descr
+
+- name: Change description of dynamic vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_present
+ description: Ansible test dynamic vlan pool
+ register: nm_add_dynamic_vlan_pool_descr
+
+- name: Verify add_dynamic_vlan_pool_descr
+ assert:
+ that:
+ - cm_add_dynamic_vlan_pool_descr is changed
+ - nm_add_dynamic_vlan_pool_descr is changed
+ - cm_add_dynamic_vlan_pool_descr.sent.fvnsVlanInstP.attributes.descr == nm_add_dynamic_vlan_pool_descr.sent.fvnsVlanInstP.attributes.descr == 'Ansible test dynamic vlan pool'
+ - cm_add_dynamic_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.allocMode == nm_add_dynamic_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - cm_add_dynamic_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.descr == nm_add_dynamic_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.descr == 'Ansible test dynamic vlan pool'
+ - cm_add_dynamic_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.name == nm_add_dynamic_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.name == 'anstest'
+ - cm_add_dynamic_vlan_pool_descr.previous == nm_add_dynamic_vlan_pool_descr.previous == cm_add_dynamic_vlan_pool_descr.current == nm_add_dynamic_vlan_pool.current
+ - nm_add_dynamic_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - nm_add_dynamic_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.descr == 'Ansible test dynamic vlan pool'
+ - nm_add_dynamic_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-dynamic'
+ - nm_add_dynamic_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.name == 'anstest'
+
+- name: Change description of dynamic vlan pool again (check_mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_present
+ description: Ansible test dynamic vlan pool
+ check_mode: true
+ register: cm_add_dynamic_vlan_pool_descr_again
+
+- name: Change description of dynamic vlan pool again (normal mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_present
+ description: Ansible test dynamic vlan pool
+ register: nm_add_dynamic_vlan_pool_descr_again
+
+- name: Verify add_dynamic_vlan_pool_descr_again
+ assert:
+ that:
+ - cm_add_dynamic_vlan_pool_descr_again is not changed
+ - nm_add_dynamic_vlan_pool_descr_again is not changed
+ - cm_add_dynamic_vlan_pool_descr_again.current == nm_add_dynamic_vlan_pool_descr_again.current == nm_add_dynamic_vlan_pool_descr.current
+
+
+# ADD VLAN POOL AGAIN
+- name: Add dynamic vlan pool again with no description (check_mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_present
+ check_mode: true
+ register: cm_add_dynamic_vlan_pool_again_no_descr
+
+- name: Add dynamic vlan pool again with no description (normal mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_present
+ register: nm_add_dynamic_vlan_pool_again_no_descr
+
+- name: Verify add_dynamic_vlan_pool_again_no_descr
+ assert:
+ that:
+ - cm_add_dynamic_vlan_pool_again_no_descr is not changed
+ - nm_add_dynamic_vlan_pool_again_no_descr is not changed
+ - cm_add_dynamic_vlan_pool_again_no_descr.current == nm_add_dynamic_vlan_pool_again_no_descr.current == nm_add_dynamic_vlan_pool_descr.current
+
+
+# QUERY ALL VLAN POOLS
+- name: Query all dynamic vlan pools (check_mode)
+ cisco.aci.aci_vlan_pool: &dynamic_vlan_pool_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_dynamic_vlan_pools
+
+- name: Query all dynamic vlan pools (normal mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_query
+ register: nm_query_all_dynamic_vlan_pools
+
+- name: Verify query_all_dynamic_vlan_pools
+ assert:
+ that:
+ - cm_query_all_dynamic_vlan_pools is not changed
+ - nm_query_all_dynamic_vlan_pools is not changed
+ - cm_query_all_dynamic_vlan_pools == nm_query_all_dynamic_vlan_pools
+ - cm_query_all_dynamic_vlan_pools.current|length >= 1
+
+
+# QUERY A VLAN POOL
+- name: Query our dynamic vlan pool
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: dynamic
+ check_mode: true
+ register: cm_query_dynamic_vlan_pool
+
+- name: Query our dynamic vlan pool
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: dynamic
+ register: nm_query_dynamic_vlan_pool
+
+- name: Verify query_dynamic_vlan_pool
+ assert:
+ that:
+ - cm_query_dynamic_vlan_pool is not changed
+ - nm_query_dynamic_vlan_pool is not changed
+ - cm_query_dynamic_vlan_pool == nm_query_dynamic_vlan_pool
+ - nm_query_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - nm_query_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.descr == 'Ansible test dynamic vlan pool'
+ - nm_query_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-dynamic'
+ - nm_query_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.name == 'anstest'
+
+
+# REMOVE VLAN POOL
+- name: Remove dynamic vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_absent
+ check_mode: true
+ register: cm_remove_dynamic_vlan_pool
+
+- name: Remove dynamic vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_absent
+ register: nm_remove_dynamic_vlan_pool
+
+- name: Verify remove_dynamic_vlan_pool
+ assert:
+ that:
+ - cm_remove_dynamic_vlan_pool is changed
+ - nm_remove_dynamic_vlan_pool is changed
+ - cm_remove_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.allocMode == cm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.allocMode == nm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.allocMode == 'dynamic'
+ - cm_remove_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.descr == cm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.descr == nm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.descr == 'Ansible test dynamic vlan pool'
+ - cm_remove_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.dn == cm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.dn == nm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-dynamic'
+ - cm_remove_dynamic_vlan_pool.current.0.fvnsVlanInstP.attributes.name == cm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.name == nm_remove_dynamic_vlan_pool.previous.0.fvnsVlanInstP.attributes.name == 'anstest'
+ - nm_remove_dynamic_vlan_pool.current == []
+
+- name: Remove dynamic vlan pool again (check_mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_absent
+ check_mode: true
+ register: cm_remove_dynamic_vlan_pool_again
+
+- name: Remove dynamic vlan pool again (normal mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_absent
+ register: nm_remove_dynamic_vlan_pool_again
+
+- name: Verify remove_dynamic_vlan_pool_again
+ assert:
+ that:
+ - cm_remove_dynamic_vlan_pool_again is not changed
+ - nm_remove_dynamic_vlan_pool_again is not changed
+ - cm_remove_dynamic_vlan_pool_again.proposed == nm_remove_dynamic_vlan_pool_again.proposed == {}
+ - cm_remove_dynamic_vlan_pool_again.sent == nm_remove_dynamic_vlan_pool_again.sent == {}
+ - cm_remove_dynamic_vlan_pool_again.previous == nm_remove_dynamic_vlan_pool_again.previous == []
+ - cm_remove_dynamic_vlan_pool_again.current == nm_remove_dynamic_vlan_pool_again.current == []
+
+
+# QUERY NON-EXISTING VLAN POOL
+- name: Query non-existing dynamic vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: dynamic
+ check_mode: true
+ register: cm_query_non_dynamic_vlan_pool
+
+- name: Query non-existing dynamic vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *dynamic_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: dynamic
+ register: nm_query_non_dynamic_vlan_pool
+
+# TODO: Implement more tests
+- name: Verify query_non_dynamic_vlan_pool
+ assert:
+ that:
+ - cm_query_non_dynamic_vlan_pool is not changed
+ - nm_query_non_dynamic_vlan_pool is not changed
+ - cm_remove_dynamic_vlan_pool_again.previous == nm_remove_dynamic_vlan_pool_again.previous == []
+ - cm_remove_dynamic_vlan_pool_again.current == nm_remove_dynamic_vlan_pool_again.current == []
+
+
+# PROVOKE ERRORS
+- name: Error when required parameter is missing
+ 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") }}'
+ state: present
+ ignore_errors: true
+ register: error_on_missing_required_param
+
+- name: Verify error_on_missing_required_param
+ assert:
+ that:
+ - error_on_missing_required_param is failed
+ - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: pool"'
+
+- name: Error when together parameter is missing
+ 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") }}'
+ pool: anstest
+ state: present
+ ignore_errors: true
+ register: error_on_missing_together_param
+
+- name: Verify error_on_missing_together_param
+ assert:
+ that:
+ - error_on_missing_together_param is failed
+ - error_on_missing_together_param.msg == "ACI requires the 'pool_allocation_mode' when 'pool' is provided"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml
new file mode 100644
index 000000000..0bac9032c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml
@@ -0,0 +1,21 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (dagwieers) <dag@wieers.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: 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
+ - include_tasks: static.yml
+ when: static is not defined or static
+
+ - include_tasks: dynamic.yml
+ when: dynamic is not defined or dynamic
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml
new file mode 100644
index 000000000..3ddae4c47
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml
@@ -0,0 +1,303 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# CLEAN ENVIRONMENT
+- name: Remove static vlan pool
+ cisco.aci.aci_vlan_pool: &static_vlan_pool_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") }}'
+ pool: anstest
+ pool_allocation_mode: static
+ state: absent
+
+# ADD VLAN POOL
+- name: Add static vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool: &static_vlan_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") }}'
+ pool: anstest
+ pool_allocation_mode: static
+ state: present
+ check_mode: true
+ register: cm_add_static_vlan_pool
+
+- name: Add static vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_present
+ register: nm_add_static_vlan_pool
+
+- name: Verify add_static_vlan_pool
+ assert:
+ that:
+ - cm_add_static_vlan_pool is changed
+ - nm_add_static_vlan_pool is changed
+ - cm_add_static_vlan_pool.sent.fvnsVlanInstP.attributes.allocMode == nm_add_static_vlan_pool.sent.fvnsVlanInstP.attributes.allocMode == 'static'
+ - cm_add_static_vlan_pool.sent.fvnsVlanInstP.attributes.name == nm_add_static_vlan_pool.sent.fvnsVlanInstP.attributes.name == 'anstest'
+ - cm_add_static_vlan_pool.proposed.fvnsVlanInstP.attributes.allocMode == nm_add_static_vlan_pool.proposed.fvnsVlanInstP.attributes.allocMode == 'static'
+ - cm_add_static_vlan_pool.proposed.fvnsVlanInstP.attributes.name == nm_add_static_vlan_pool.proposed.fvnsVlanInstP.attributes.name == 'anstest'
+ - cm_add_static_vlan_pool.previous == nm_add_static_vlan_pool.previous == []
+ # NOTE: We cannot fix this easily
+ - cm_add_static_vlan_pool.current == []
+ - nm_add_static_vlan_pool.current.0.fvnsVlanInstP.attributes.allocMode == 'static'
+ - nm_add_static_vlan_pool.current.0.fvnsVlanInstP.attributes.descr == ''
+ - nm_add_static_vlan_pool.current.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-static'
+ - nm_add_static_vlan_pool.current.0.fvnsVlanInstP.attributes.name == 'anstest'
+ - nm_add_static_vlan_pool.current.0.fvnsVlanInstP.attributes.annotation == 'orchestrator:ansible'
+
+- name: Add static_vlan_pool again (check_mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_present
+ check_mode: true
+ register: cm_add_static_vlan_pool_again
+
+- name: Add static vlan pool again (normal mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_present
+ register: nm_add_static_vlan_pool_again
+
+- name: Verify add_static_vlan_pool_again
+ assert:
+ that:
+ - cm_add_static_vlan_pool_again is not changed
+ - nm_add_static_vlan_pool_again is not changed
+ - cm_add_static_vlan_pool_again.current == nm_add_static_vlan_pool_again.current == nm_add_static_vlan_pool.current
+
+
+# CHANGE VLAN POOL
+- name: Change description of static vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_present
+ description: Ansible test static vlan pool
+ check_mode: true
+ register: cm_add_static_vlan_pool_descr
+
+- name: Change description of static vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_present
+ description: Ansible test static vlan pool
+ register: nm_add_static_vlan_pool_descr
+
+- name: Verify add_static_vlan_pool_descr
+ assert:
+ that:
+ - cm_add_static_vlan_pool_descr is changed
+ - nm_add_static_vlan_pool_descr is changed
+ - cm_add_static_vlan_pool_descr.sent.fvnsVlanInstP.attributes.descr == nm_add_static_vlan_pool_descr.sent.fvnsVlanInstP.attributes.descr == 'Ansible test static vlan pool'
+ - cm_add_static_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.allocMode == nm_add_static_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.allocMode == 'static'
+ - cm_add_static_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.descr == nm_add_static_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.descr == 'Ansible test static vlan pool'
+ - cm_add_static_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.name == nm_add_static_vlan_pool_descr.proposed.fvnsVlanInstP.attributes.name == 'anstest'
+ - cm_add_static_vlan_pool_descr.previous == nm_add_static_vlan_pool_descr.previous == cm_add_static_vlan_pool_descr.current == nm_add_static_vlan_pool.current
+ - nm_add_static_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.allocMode == 'static'
+ - nm_add_static_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.descr == 'Ansible test static vlan pool'
+ - nm_add_static_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-static'
+ - nm_add_static_vlan_pool_descr.current.0.fvnsVlanInstP.attributes.name == 'anstest'
+
+- name: Change description of static vlan pool again (check_mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_present
+ description: Ansible test static vlan pool
+ check_mode: true
+ register: cm_add_static_vlan_pool_descr_again
+
+- name: Change description of static vlan pool again (normal mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_present
+ description: Ansible test static vlan pool
+ register: nm_add_static_vlan_pool_descr_again
+
+- name: Verify add_static_vlan_pool_descr_again
+ assert:
+ that:
+ - cm_add_static_vlan_pool_descr_again is not changed
+ - nm_add_static_vlan_pool_descr_again is not changed
+ - cm_add_static_vlan_pool_descr_again.current == nm_add_static_vlan_pool_descr_again.current == nm_add_static_vlan_pool_descr.current
+
+
+# ADD VLAN POOL AGAIN
+- name: Add static vlan pool again with no description (check_mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_present
+ check_mode: true
+ register: cm_add_static_vlan_pool_again_no_descr
+
+- name: Add static vlan pool again with no description (normal mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_present
+ register: nm_add_static_vlan_pool_again_no_descr
+
+- name: Verify add_static_vlan_pool_again_no_descr
+ assert:
+ that:
+ - cm_add_static_vlan_pool_again_no_descr is not changed
+ - nm_add_static_vlan_pool_again_no_descr is not changed
+ - cm_add_static_vlan_pool_again_no_descr.current == nm_add_static_vlan_pool_again_no_descr.current == nm_add_static_vlan_pool_descr.current
+
+
+# QUERY ALL VLAN POOLS
+- name: Query all static vlan pools (check_mode)
+ cisco.aci.aci_vlan_pool: &static_vlan_pool_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") }}'
+ state: query
+ check_mode: true
+ register: cm_query_all_static_vlan_pools
+
+- name: Query all static vlan pools (normal mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_query
+ register: nm_query_all_static_vlan_pools
+
+- name: Verify query_all_static_vlan_pools
+ assert:
+ that:
+ - cm_query_all_static_vlan_pools is not changed
+ - nm_query_all_static_vlan_pools is not changed
+ - cm_query_all_static_vlan_pools == nm_query_all_static_vlan_pools
+ - cm_query_all_static_vlan_pools.current|length >= 1
+
+
+# QUERY A VLAN POOL
+- name: Query our static vlan pool
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: static
+ check_mode: true
+ register: cm_query_static_vlan_pool
+
+- name: Query our static vlan pool
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: static
+ register: nm_query_static_vlan_pool
+
+- name: Verify query_static_vlan_pool
+ assert:
+ that:
+ - cm_query_static_vlan_pool is not changed
+ - nm_query_static_vlan_pool is not changed
+ - cm_query_static_vlan_pool == nm_query_static_vlan_pool
+ - nm_query_static_vlan_pool.current.0.fvnsVlanInstP.attributes.allocMode == 'static'
+ - nm_query_static_vlan_pool.current.0.fvnsVlanInstP.attributes.descr == 'Ansible test static vlan pool'
+ - nm_query_static_vlan_pool.current.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-static'
+ - nm_query_static_vlan_pool.current.0.fvnsVlanInstP.attributes.name == 'anstest'
+
+
+# REMOVE VLAN POOL
+- name: Remove static vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_absent
+ check_mode: true
+ register: cm_remove_static_vlan_pool
+
+- name: Remove static vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_absent
+ register: nm_remove_static_vlan_pool
+
+- name: Verify remove_static_vlan_pool
+ assert:
+ that:
+ - cm_remove_static_vlan_pool is changed
+ - nm_remove_static_vlan_pool is changed
+ - cm_remove_static_vlan_pool.current.0.fvnsVlanInstP.attributes.allocMode == cm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.allocMode == nm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.allocMode == 'static'
+ - cm_remove_static_vlan_pool.current.0.fvnsVlanInstP.attributes.descr == cm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.descr == nm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.descr == 'Ansible test static vlan pool'
+ - cm_remove_static_vlan_pool.current.0.fvnsVlanInstP.attributes.dn == cm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.dn == nm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.dn == 'uni/infra/vlanns-[anstest]-static'
+ - cm_remove_static_vlan_pool.current.0.fvnsVlanInstP.attributes.name == cm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.name == nm_remove_static_vlan_pool.previous.0.fvnsVlanInstP.attributes.name == 'anstest'
+ - nm_remove_static_vlan_pool.current == []
+
+- name: Remove static vlan pool again (check_mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_absent
+ check_mode: true
+ register: cm_remove_static_vlan_pool_again
+
+- name: Remove static vlan pool again (normal mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_absent
+ register: nm_remove_static_vlan_pool_again
+
+- name: Verify remove_static_vlan_pool_again
+ assert:
+ that:
+ - cm_remove_static_vlan_pool_again is not changed
+ - nm_remove_static_vlan_pool_again is not changed
+ - cm_remove_static_vlan_pool_again.proposed == nm_remove_static_vlan_pool_again.proposed == {}
+ - cm_remove_static_vlan_pool_again.sent == nm_remove_static_vlan_pool_again.sent == {}
+ - cm_remove_static_vlan_pool_again.previous == nm_remove_static_vlan_pool_again.previous == []
+ - cm_remove_static_vlan_pool_again.current == nm_remove_static_vlan_pool_again.current == []
+
+
+# QUERY NON-EXISTING VLAN POOL
+- name: Query non-existing static vlan pool (check_mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: static
+ check_mode: true
+ register: cm_query_non_static_vlan_pool
+
+- name: Query non-existing static vlan pool (normal mode)
+ cisco.aci.aci_vlan_pool:
+ <<: *static_vlan_pool_query
+ pool: anstest
+ pool_allocation_mode: static
+ register: nm_query_non_static_vlan_pool
+
+# TODO: Implement more tests
+- name: Verify query_non_static_vlan_pool
+ assert:
+ that:
+ - cm_query_non_static_vlan_pool is not changed
+ - nm_query_non_static_vlan_pool is not changed
+ - cm_remove_static_vlan_pool_again.previous == nm_remove_static_vlan_pool_again.previous == []
+ - cm_remove_static_vlan_pool_again.current == nm_remove_static_vlan_pool_again.current == []
+
+
+# PROVOKE ERRORS
+- name: Error when required parameter is missing
+ 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") }}'
+ state: present
+ ignore_errors: true
+ register: error_on_missing_required_param
+
+- name: Verify error_on_missing_required_param
+ assert:
+ that:
+ - error_on_missing_required_param is failed
+ - 'error_on_missing_required_param.msg == "state is present but all of the following are missing: pool"'
+
+- name: Error when together parameter is missing
+ 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") }}'
+ pool: anstest
+ state: present
+ ignore_errors: true
+ register: error_on_missing_together_param
+
+- name: Verify error_on_missing_together_param
+ assert:
+ that:
+ - error_on_missing_together_param is failed
+ - error_on_missing_together_param.msg == "ACI requires the 'pool_allocation_mode' when 'pool' is provided"
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..c39259593
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml
@@ -0,0 +1,378 @@
+# Test code for the ACI modules
+
+# Copyright: (c) 2017, Jacob McGill (jmcgill298)
+# Copyright: (c) 2018, Dag Wieers (dagwieers) <dag@wieers.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: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when: query_cloud.current == [] # This condition will execute only non-cloud sites
+ block: # block specifies execution of tasks within, based on conditions
+ - name: Ensure vlan pool exists for tests to kick off
+ 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") }}'
+ state: absent
+ pool: anstest
+ pool_allocation_mode: static
+ description: Ansible Test
+
+ - name: Ensure vlan pool exists for tests to kick off
+ cisco.aci.aci_vlan_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: debug
+ state: present
+ pool: anstest
+ pool_allocation_mode: static
+ description: Ansible Test
+ register: pool_present
+
+ - name: Create vlan pool encap block - check mode works
+ cisco.aci.aci_vlan_pool_encap_block: &aci_encap_block_present
+ <<: *aci_pool_present
+ block_name: anstest
+ block_start: 20
+ block_end: 40
+ pool: anstest
+ pool_allocation_mode: static
+ allocation_mode: inherit
+ description: Ansible Test
+ check_mode: true
+ register: encap_block_present_check_mode
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_present_check_mode is changed
+ - encap_block_present_check_mode.sent.fvnsEncapBlk.attributes.allocMode == 'inherit'
+ - encap_block_present_check_mode.sent.fvnsEncapBlk.attributes.descr == 'Ansible Test'
+ - encap_block_present_check_mode.sent.fvnsEncapBlk.attributes.from == 'vlan-20'
+ - encap_block_present_check_mode.sent.fvnsEncapBlk.attributes.to == 'vlan-40'
+ - encap_block_present_check_mode.sent.fvnsEncapBlk.attributes.name == 'anstest'
+
+ - name: Create vlan pool encap_block - creation works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ register: encap_block_present
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_present is changed
+ - encap_block_present.previous == []
+ - encap_block_present.sent == encap_block_present_check_mode.sent
+ - encap_block_present.sent == encap_block_present.proposed
+ - encap_block_present.current.0.fvnsEncapBlk.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Create vlan pool range - idempotency works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ register: encap_block_present_idempotent
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_present_idempotent is not changed
+ - encap_block_present_idempotent.previous.0.fvnsEncapBlk.attributes.name == "anstest"
+
+ - name: Update vlan pool range - update works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ description: Ansible Test Update
+ allocation_mode: inherit
+ register: encap_block_present_update
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_present_update is changed
+ - encap_block_present_update.previous != []
+ - encap_block_present_update.sent != encap_block_present.sent
+
+ - name: Create vlan pool range - used for query
+ cisco.aci.aci_vlan_pool_encap_block: &aci_encap_block_present_2
+ <<: *aci_encap_block_present
+ block_name: anstest_2
+ block_start: 50
+ block_end: 55
+ register: encap_block_present_2
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_present_2 is changed
+ - encap_block_present_2.previous == []
+
+ - name: Invalid encap_block_start - error message works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ block_start: 0
+ ignore_errors: true
+ register: encap_block_start_low
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_start_low is failed
+ - encap_block_start_low.msg == "vlan pools must have 'block_start' and 'block_end' values between 1 and 4094"
+
+ - name: Invalid encap_block_start - error message works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ block_start: 4096
+ ignore_errors: true
+ register: encap_block_start_high
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_start_high is failed
+ - encap_block_start_high.msg == "vlan pools must have 'block_start' and 'block_end' values between 1 and 4094"
+
+ - name: Invalid encap_block_end - error message works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ block_end: 0
+ ignore_errors: true
+ register: encap_block_end_low
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_end_low is failed
+ - encap_block_end_low.msg == "vlan pools must have 'block_start' and 'block_end' values between 1 and 4094"
+
+ - name: Invalid encap_block_end - error message works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ block_end: 4096
+ ignore_errors: true
+ register: encap_block_end_high
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_end_high is failed
+ - encap_block_end_high.msg == "vlan pools must have 'block_start' and 'block_end' values between 1 and 4094"
+
+ - name: Range start higher than range end - error message works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ block_start: 1000
+ ignore_errors: true
+ register: encap_block_start_end
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_start_end is failed
+ - encap_block_start_end.msg == "The 'block_start' must be less than or equal to the 'block_end'"
+
+ - name: Missing required param - error message works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_pool_present
+ ignore_errors: true
+ register: encap_block_present_missing_param
+
+ - name: Present assertions
+ assert:
+ that:
+ - encap_block_present_missing_param is failed
+ - 'encap_block_present_missing_param.msg == "state is present but all of the following are missing: block_end, block_start"'
+
+ - name: Query specific vlan pool range
+ cisco.aci.aci_vlan_pool_encap_block: &aci_encap_block_query
+ <<: *aci_encap_block_present
+ state: query
+ register: encap_block_query
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query is not changed
+ - encap_block_query.url.endswith("infra/vlanns-[anstest]-static/from-[vlan-20]-to-[vlan-40].json")
+ - encap_block_query.current | length == 1
+ - encap_block_query.current.0.fvnsEncapBlk.attributes.name == "anstest"
+
+ - name: Query vlan pool range - from, to, and name are filtered
+ cisco.aci.aci_vlan_pool_encap_block: &aci_encap_block_query_filter
+ <<: *aci_encap_block_query
+ pool: "{{ fake_var | default(omit) }}"
+ register: encap_block_query_from_to_name
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query_from_to_name is not changed
+ - encap_block_query_from_to_name.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.from,\"vlan-20\")" in encap_block_query_from_to_name.filter_string'
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in encap_block_query_from_to_name.filter_string'
+ - '"eq(fvnsEncapBlk.to,\"vlan-40\")" in encap_block_query_from_to_name.filter_string'
+ - encap_block_query_from_to_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+ - encap_block_query_from_to_name.current.0.fvnsEncapBlk.attributes.from == "vlan-20"
+ - encap_block_query_from_to_name.current.0.fvnsEncapBlk.attributes.to == "vlan-40"
+
+ - name: Query vlan pool range - from and name are filtered
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_query_filter
+ block_end: "{{ fake_var | default(omit) }}"
+ register: encap_block_query_from_name
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query_from_name is not changed
+ - encap_block_query_from_name.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.from,\"vlan-20\")" in encap_block_query_from_name.filter_string'
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in encap_block_query_from_name.filter_string'
+ - encap_block_query_from_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+ - encap_block_query_from_name.current.0.fvnsEncapBlk.attributes.from == "vlan-20"
+
+ - name: Query vlan pool range - to and name are filtered
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_query_filter
+ block_start: "{{ fake_var | default(omit) }}"
+ register: encap_block_query_to_name
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query_to_name is not changed
+ - encap_block_query_to_name.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in encap_block_query_to_name.filter_string'
+ - '"eq(fvnsEncapBlk.to,\"vlan-40\")" in encap_block_query_to_name.filter_string'
+ - encap_block_query_to_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+ - encap_block_query_to_name.current.0.fvnsEncapBlk.attributes.to == "vlan-40"
+
+ - name: Query vlan pool range - name is filtered
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_query_filter
+ block_start: "{{ fake_var | default(omit) }}"
+ block_end: "{{ fake_var | default(omit) }}"
+ register: encap_block_query_name
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query_name is not changed
+ - encap_block_query_name.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.name,\"anstest\")" in encap_block_query_name.filter_string'
+ - encap_block_query_name.current.0.fvnsEncapBlk.attributes.name == "anstest"
+
+ - name: Query vlan pool range - from and to are filtered
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_query_filter
+ block_name: "{{ fake_var | default(omit) }}"
+ register: encap_block_query_from_to
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query_from_to is not changed
+ - encap_block_query_from_to.url.endswith("class/fvnsEncapBlk.json")
+ - '"eq(fvnsEncapBlk.from,\"vlan-20\")" in encap_block_query_from_to.filter_string'
+ - '"eq(fvnsEncapBlk.to,\"vlan-40\")" in encap_block_query_from_to.filter_string'
+ - encap_block_query_from_to.current.0.fvnsEncapBlk.attributes.from == "vlan-20"
+ - encap_block_query_from_to.current.0.fvnsEncapBlk.attributes.to == "vlan-40"
+
+ - name: Query all ranges in a vlan pool
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_pool_present
+ state: query
+ pool_allocation_mode: static
+ register: encap_block_query_pool
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query_pool is not changed
+ - encap_block_query_pool.current | length == 1
+ - encap_block_query_pool.current.0.fvnsVlanInstP.attributes.name == "anstest"
+ - encap_block_query_pool.current.0.fvnsVlanInstP.children | length > 1
+ - encap_block_query_pool.url.endswith("infra/vlanns-[anstest]-static.json")
+
+ - name: Query all ranges
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_pool_present
+ state: query
+ pool: "{{ fake_var | default(omit) }}"
+ register: encap_block_query_all
+
+ - name: Query assertions
+ assert:
+ that:
+ - encap_block_query_all is not changed
+ - encap_block_query_all.current | length > 1
+ - encap_block_query_all.current.0.fvnsEncapBlk is defined
+ - encap_block_query_all.url.endswith("class/fvnsEncapBlk.json")
+
+ - name: Delete vlan pool range - deletion works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ state: absent
+ register: delete_range
+
+ - name: Absent assertions
+ assert:
+ that:
+ - delete_range is changed
+ - delete_range.proposed == {}
+ - delete_range.previous.0.fvnsEncapBlk.attributes.name == "anstest"
+
+ - name: Delete vlan pool range - check mode works
+ cisco.aci.aci_vlan_pool_encap_block: &aci_encap_block_absent
+ <<: *aci_encap_block_present_2
+ state: absent
+ check_mode: true
+ register: delete_check_mode
+
+ - name: Absent assertions
+ assert:
+ that:
+ - delete_check_mode is changed
+ - delete_check_mode.previous != []
+
+ - name: Delete vlan pool range - deletion works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_absent
+ register: delete_encap_block_2
+
+ - name: Absent assertions
+ assert:
+ that:
+ - delete_encap_block_2 is changed
+ - delete_encap_block_2.previous == delete_check_mode.previous
+
+ - name: Delete vlan pool range again - idempotency works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_absent
+ register: delete_idempotent
+
+ - name: Absent assertions
+ assert:
+ that:
+ - delete_idempotent is not changed
+ - delete_idempotent.previous == []
+
+ - name: Cleanup vlan pool
+ cisco.aci.aci_vlan_pool:
+ <<: *aci_pool_present
+ state: absent
+ when: pool_present is changed
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml
new file mode 100644
index 000000000..7a02169b0
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_controller/tasks/main.yml
@@ -0,0 +1,164 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Anvitha Jain (@anvitha-jain) <anvjain@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# Remove VMM domain
+- name: Remove VMM domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: "{{ item }}"
+ state: absent
+ register: nm_remove_domain
+ loop:
+ - vmware
+ - redhat
+ - microsoft
+ - openstack
+
+- 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:
+ # ADD DOMAIN
+ - name: Add VMM domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: "{{ item }}"
+ state: present
+ register: nm_add_domain
+ loop:
+ - vmware
+ - redhat
+ - microsoft
+ - openstack
+
+ - name: Verify VMM add_domain
+ assert:
+ that:
+ - nm_add_domain is changed
+
+ - name: Add controller to VMware VMM domain
+ aci_vmm_controller: &add_controller
+ <<: *aci_info
+ domain: vmm_dom
+ name: vCenter1
+ controller_hostname: 10.1.1.1
+ dvs_version: unmanaged
+ vm_provider: vmware
+ datacenter: DC1
+ state: present
+ register: nm_add_controller
+
+ - name: Verify VMM add_controller
+ assert:
+ that:
+ - nm_add_controller is changed
+ - nm_add_controller.sent.vmmCtrlrP.attributes.name == 'vCenter1'
+ - nm_add_controller.proposed.vmmCtrlrP.attributes.name == 'vCenter1'
+ - nm_add_controller.previous == []
+ - nm_add_controller.current.0.vmmCtrlrP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/ctrlr-vCenter1'
+ - nm_add_controller.current.0.vmmCtrlrP.attributes.name == 'vCenter1'
+ - nm_add_controller.current.0.vmmCtrlrP.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add another controller to all VMM domain
+ aci_vmm_controller:
+ <<: *add_controller
+ name: vCenter2
+ credentials: vCenterCredentials1
+ inband_management_epg: ib_epg
+ controller_hostname: 10.10.1.1
+ vm_provider: "{{ item }}"
+ state: present
+ register: add_controller
+ loop:
+ - vmware
+ - redhat
+ - microsoft
+ - openstack
+
+ - name: Verify another VMM add_controller
+ assert:
+ that:
+ - add_controller is changed
+
+ - name: Add controller to VMware VMM domain again
+ aci_vmm_controller:
+ <<: *add_controller
+ name: vCenter2
+ controller_hostname: 10.10.1.1
+ state: present
+ register: add_controller_again
+
+ - name: Verify another VMM add_controller again
+ assert:
+ that:
+ - add_controller_again is not changed
+
+ - name: Query controller
+ aci_vmm_controller:
+ <<: *aci_info
+ domain: vmm_dom
+ name: vCenter1
+ vm_provider: vmware
+ state: query
+ register: query_controller
+
+ - name: Verify VMM query_controller
+ assert:
+ that:
+ - query_controller is not changed
+ - query_controller.current.0.vmmCtrlrP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/ctrlr-vCenter1'
+ - query_controller.current.0.vmmCtrlrP.attributes.name == 'vCenter1'
+
+ - name: Query all controllers
+ aci_vmm_controller:
+ <<: *aci_info
+ domain: vmm_dom
+ vm_provider: vmware
+ state: query
+ register: query_controller
+
+ - name: Verify VMM query_controller
+ assert:
+ that:
+ - query_controller is not changed
+
+ - name: Delete controllers
+ aci_vmm_controller:
+ <<: *add_controller
+ name: vCenter1
+ state: absent
+ register: remove_controller
+
+ - name: Delete controllers
+ aci_vmm_controller:
+ <<: *add_controller
+ name: vCenter2
+ state: absent
+ register: remove_controller_2
+
+ - name: Verify VMM remove_controller
+ assert:
+ that:
+ - remove_controller is changed
+ - remove_controller_2 is changed
+ - remove_controller_2.current == [] \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml
new file mode 100644
index 000000000..b76c4563a
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml
@@ -0,0 +1,12 @@
+# Test code for the ACI modules
+# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.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
+
+- include_tasks: vmware.yml
+ when: vmware is not defined or vmware \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml
new file mode 100644
index 000000000..262ecf33c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml
@@ -0,0 +1,221 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("info") }}'
+
+# Remove VMM domain
+- name: Remove VMM domain (normal mode)
+ cisco.aci.aci_domain: &domain_absent
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: vmware
+ state: absent
+ register: nm_remove_domain
+
+- 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:
+ # ADD VMM domain for testing
+ - name: Add VMM domain (normal mode)
+ cisco.aci.aci_domain: &domain_present
+ <<: *aci_info
+ domain: vmm_dom
+ domain_type: vmm
+ vm_provider: vmware
+ state: present
+ register: nm_add_domain
+
+ - name: Verify add_domain
+ assert:
+ that:
+ - nm_add_domain is changed
+
+ # REMOVE credential
+ - name: Remove credential (check mode)
+ cisco.aci.aci_vmm_credential: &credential_absent
+ <<: *aci_info
+ name: vmm_cred
+ description: my_new_cred
+ domain: vmm_dom
+ credential_username: myUsername
+ credential_password: mySecretPassword
+ vm_provider: vmware
+ state: absent
+ check_mode: true
+ register: cm_remove_credential
+
+ - name: Remove vmware VMM credential (normal mode)
+ cisco.aci.aci_vmm_credential: *credential_absent
+ register: nm_remove_credential
+
+ - name: Verify remove_credential
+ assert:
+ that:
+ - cm_remove_credential is not changed
+ - nm_remove_credential is not changed
+
+ # ADD credential
+ - name: Add vmware VMM credential (check mode)
+ cisco.aci.aci_vmm_credential: &credential_present
+ <<: *aci_info
+ name: vmm_cred
+ description: my_new_cred
+ domain: vmm_dom
+ credential_username: myUsername
+ credential_password: mySecretPassword
+ vm_provider: vmware
+ state: present
+ check_mode: true
+ register: cm_add_credential
+
+ # NOTE: Setting password is not idempotent
+ - name: Add vmware VMM credential (normal mode)
+ cisco.aci.aci_vmm_credential: *credential_present
+ register: nm_add_credential
+
+ # NOTE: Setting password is not idempotent
+ - name: Add vmware VMM credential again (check mode)
+ cisco.aci.aci_vmm_credential: *credential_present
+ check_mode: true
+ register: cm_add_credential_again
+
+ - name: Verify add_credential
+ assert:
+ that:
+ - cm_add_credential is changed
+ - nm_add_credential is changed
+ - cm_add_credential.sent.vmmUsrAccP.attributes.descr == nm_add_credential.sent.vmmUsrAccP.attributes.descr == 'my_new_cred'
+ - cm_add_credential.sent.vmmUsrAccP.attributes.name == nm_add_credential.sent.vmmUsrAccP.attributes.name == 'vmm_cred'
+ - cm_add_credential.sent.vmmUsrAccP.attributes.pwd == nm_add_credential.sent.vmmUsrAccP.attributes.pwd == 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
+ - cm_add_credential.sent.vmmUsrAccP.attributes.usr == nm_add_credential.sent.vmmUsrAccP.attributes.usr == 'myUsername'
+ - cm_add_credential.proposed.vmmUsrAccP.attributes.descr == nm_add_credential.proposed.vmmUsrAccP.attributes.descr == 'my_new_cred'
+ - cm_add_credential.proposed.vmmUsrAccP.attributes.name == nm_add_credential.proposed.vmmUsrAccP.attributes.name == 'vmm_cred'
+ - cm_add_credential.proposed.vmmUsrAccP.attributes.pwd == nm_add_credential.proposed.vmmUsrAccP.attributes.pwd == 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
+ - cm_add_credential.proposed.vmmUsrAccP.attributes.usr == nm_add_credential.proposed.vmmUsrAccP.attributes.usr == 'myUsername'
+ - cm_add_credential.current == cm_add_credential.previous == nm_add_credential.previous == []
+ - nm_add_credential.current.0.vmmUsrAccP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/usracc-vmm_cred'
+ - nm_add_credential.current.0.vmmUsrAccP.attributes.name == 'vmm_cred'
+ - nm_add_credential.current.0.vmmUsrAccP.attributes.annotation == 'orchestrator:ansible'
+
+ # MODIFY credential
+ - name: Modify vmware VMM credential (check mode)
+ cisco.aci.aci_vmm_credential: &credential_mod
+ <<: *aci_info
+ name: vmm_cred
+ description: my_updated_descr
+ domain: vmm_dom
+ credential_username: myNewUsername
+ credential_password: myNewSecretPassword
+ vm_provider: vmware
+ state: present
+ check_mode: true
+ register: cm_mod_credential
+
+ - name: Modify vmware VMM credential (normal mode)
+ cisco.aci.aci_vmm_credential: *credential_mod
+ register: nm_mod_credential
+
+ - name: Verify mod_credential
+ assert:
+ that:
+ - cm_mod_credential is changed
+ - nm_mod_credential is changed
+ - cm_mod_credential.sent.vmmUsrAccP.attributes.descr == nm_mod_credential.sent.vmmUsrAccP.attributes.descr == 'my_updated_descr'
+ - cm_mod_credential.sent.vmmUsrAccP.attributes.pwd == nm_mod_credential.sent.vmmUsrAccP.attributes.pwd == 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
+ - cm_mod_credential.sent.vmmUsrAccP.attributes.usr == nm_mod_credential.sent.vmmUsrAccP.attributes.usr == 'myNewUsername'
+ - cm_mod_credential.proposed.vmmUsrAccP.attributes.descr == nm_mod_credential.proposed.vmmUsrAccP.attributes.descr == 'my_updated_descr'
+ - cm_mod_credential.proposed.vmmUsrAccP.attributes.name == nm_mod_credential.proposed.vmmUsrAccP.attributes.name == 'vmm_cred'
+ - cm_mod_credential.proposed.vmmUsrAccP.attributes.pwd == nm_mod_credential.proposed.vmmUsrAccP.attributes.pwd == 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
+ - cm_mod_credential.proposed.vmmUsrAccP.attributes.usr == nm_mod_credential.proposed.vmmUsrAccP.attributes.usr == 'myNewUsername'
+ - nm_mod_credential.current.0.vmmUsrAccP.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/usracc-vmm_cred'
+ - nm_mod_credential.current.0.vmmUsrAccP.attributes.name == 'vmm_cred'
+
+ - name: Query existing vmware VMM credential (check mode)
+ cisco.aci.aci_vmm_credential: &query_existing_cred
+ <<: *aci_info
+ name: vmm_cred
+ domain: vmm_dom
+ vm_provider: vmware
+ state: query
+ check_mode: true
+ register: cm_query_credential
+
+ - name: Query existing vmware VMM credential (normal mode)
+ cisco.aci.aci_vmm_credential: *query_existing_cred
+ register: nm_query_credential
+
+ - name: Query non-existent vmware VMM credential
+ cisco.aci.aci_vmm_credential:
+ <<: *aci_info
+ name: vmm_fake_cred
+ domain: vmm_dom
+ vm_provider: vmware
+ state: query
+ register: nm_query_fake_credential
+
+ - name: Query all vmware VMM credentials (check mode)
+ cisco.aci.aci_vmm_credential: &query_all_creds
+ <<: *aci_info
+ vm_provider: vmware
+ state: query
+ check_mode: true
+ register: cm_query_all_credential
+
+ - name: Query all vmware VMM credentials (normal mode)
+ cisco.aci.aci_vmm_credential: *query_all_creds
+ register: nm_query_all_credential
+
+ - name: Verify query_credential
+ assert:
+ that:
+ - cm_query_credential is not changed
+ - nm_query_credential is not changed
+ - nm_query_fake_credential is not changed
+ - cm_query_all_credential is not changed
+ - nm_query_all_credential is not changed
+ - cm_query_credential.current.0.vmmUsrAccP.attributes.name == 'vmm_cred'
+ - nm_query_credential.current.0.vmmUsrAccP.attributes.name == 'vmm_cred'
+ - nm_query_fake_credential.current == []
+ - cm_query_all_credential.current.0.vmmUsrAccP.attributes.name == 'vmm_cred'
+ - nm_query_all_credential.current.0.vmmUsrAccP.attributes.name == 'vmm_cred'
+
+ - name: Remove credential (check_mode)
+ cisco.aci.aci_vmm_credential: *credential_absent
+ check_mode: true
+ register: cm_remove_credential_again
+
+ - name: Remove credential (normal_mode)
+ cisco.aci.aci_vmm_credential: *credential_absent
+ register: nm_remove_credential_again
+
+ - name: Remove credential (normal_mode)
+ cisco.aci.aci_vmm_credential: *credential_absent
+ register: nm_remove_credential_final
+
+ - name: Verify remove_credential
+ assert:
+ that:
+ - cm_remove_credential_again is changed
+ - nm_remove_credential_again is changed
+ - nm_remove_credential_final is not changed
+
+ # Remove VMM domain after testing
+ - name: Remove VMM domain (normal_mode)
+ cisco.aci.aci_domain: *domain_absent
+ register: nm_remove_domain_again
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml
new file mode 100644
index 000000000..1e7b6a6cf
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink/tasks/main.yml
@@ -0,0 +1,175 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# PERFORM TESTS ONLY ON SUPPORTED APICS
+- name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when:
+ - query_cloud.current == [] # This condition will skip execution for cloud sites
+ - version.current.0.topSystem.attributes.version is version('4.2', '>=') # Make sure we execute it for APIC version above or equal to 4.2
+ block:
+ # CLEAN ENVIRONMENT
+ - name: Remove ansible_domain if it already exists
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_domain
+ domain_type: vmm
+ vm_provider: vmware
+ state: absent
+
+ # CREATE VMWARE DOMAIN
+ - name: Create ansible_domain
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_domain
+ domain_type: vmm
+ vm_provider: vmware
+ state: present
+
+ # CREATE VMWARE UPLINK CONTAINER
+ - name: Create VMWare Uplink Container
+ aci_vmm_uplink_container:
+ <<: *aci_info
+ domain: ansible_domain
+ num_of_uplinks: 1
+ state: present
+
+ # CREATE VMWARE UPLINK
+ - name: Create VMWare Uplink
+ cisco.aci.aci_vmm_uplink:
+ <<: *aci_info
+ domain: ansible_domain
+ uplink_id: 1
+ uplink_name: uplink1
+ state: present
+ register: create_uplink
+
+ - name: Verify Uplink Creation
+ assert:
+ that:
+ - create_uplink.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1"
+ - create_uplink.current.0.vmmUplinkP.attributes.uplinkId == "1"
+ - create_uplink.current.0.vmmUplinkP.attributes.uplinkName == "uplink1"
+ - create_uplink.current.0.vmmUplinkP.attributes.annotation == 'orchestrator:ansible'
+
+ # CREATE VMWARE UPLINK AGAIN TO TEST IDEMPOTENCE
+ - name: Create VMWare Uplink again
+ cisco.aci.aci_vmm_uplink:
+ <<: *aci_info
+ domain: ansible_domain
+ uplink_id: 1
+ uplink_name: uplink1
+ state: present
+ register: create_uplink_again
+
+ - name: Verify Uplink Creation idempotence
+ assert:
+ that:
+ - create_uplink_again is not changed
+ - create_uplink_again.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1"
+ - create_uplink_again.current.0.vmmUplinkP.attributes.uplinkId == "1"
+ - create_uplink_again.current.0.vmmUplinkP.attributes.uplinkName == "uplink1"
+
+ # MODIFY VMWARE UPLINK
+ - name: Create VMWare Uplink again
+ cisco.aci.aci_vmm_uplink:
+ <<: *aci_info
+ domain: ansible_domain
+ uplink_id: 1
+ uplink_name: updated_uplink
+ state: present
+ register: update_uplink
+
+ - name: Verify Uplink update
+ assert:
+ that:
+ - update_uplink is changed
+ - update_uplink.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1"
+ - update_uplink.current.0.vmmUplinkP.attributes.uplinkId == "1"
+ - update_uplink.current.0.vmmUplinkP.attributes.uplinkName == "updated_uplink"
+
+ # QUERY VMWARE UPLINK
+ - name: Query VMWare Uplink
+ cisco.aci.aci_vmm_uplink:
+ <<: *aci_info
+ domain: ansible_domain
+ uplink_id: 1
+ state: query
+ register: query_uplink
+
+ - name: Verify Uplink query
+ assert:
+ that:
+ - query_uplink is not changed
+ - query_uplink.current.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1"
+ - query_uplink.current.0.vmmUplinkP.attributes.uplinkId == "1"
+ - query_uplink.current.0.vmmUplinkP.attributes.uplinkName == "updated_uplink"
+
+ # DELETE VMWARE UPLINK
+ - name: Delete VMWare Uplink
+ cisco.aci.aci_vmm_uplink:
+ <<: *aci_info
+ domain: ansible_domain
+ uplink_id: 1
+ state: absent
+ register: remove_uplink
+
+ - name: Verify VMWare Uplink deletion
+ assert:
+ that:
+ - remove_uplink is changed
+ - remove_uplink.current == []
+ - remove_uplink.previous.0.vmmUplinkP.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont/uplinkp-1"
+ - remove_uplink.previous.0.vmmUplinkP.attributes.uplinkId == "1"
+ - remove_uplink.previous.0.vmmUplinkP.attributes.uplinkName == "updated_uplink"
+
+ # DELETE VMWARE UPLINK AGAIN TO TEST IDEMPOTENCE
+ - name: Delete VMWare Uplink again
+ cisco.aci.aci_vmm_uplink:
+ <<: *aci_info
+ domain: ansible_domain
+ uplink_id: 1
+ state: absent
+ register: remove_uplink_again
+
+ - name: Verify VMWare Uplink deletion idempotence
+ assert:
+ that:
+ - remove_uplink_again is not changed
+
+ # CLEAN UP
+ - name: Remove ansible_domain
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_domain
+ domain_type: vmm
+ vm_provider: vmware
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml
new file mode 100644
index 000000000..0ddbe2174
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_uplink_container/tasks/main.yml
@@ -0,0 +1,156 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, 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
+
+# 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
+
+# PERFORM TESTS ONLY ON SUPPORTED APICS
+- name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Verify Cloud and Non-Cloud Sites in use.
+ include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml
+
+- name: Execute tasks only for non-cloud sites
+ when:
+ - query_cloud.current == [] # This condition will skip execution for cloud sites
+ - version.current.0.topSystem.attributes.version is version('4.2', '>=') # Make sure we execute it for APIC version above or equal to 4.2
+ block:
+ # CLEAN ENVIRONMENT
+ - name: Remove ansible_domain if it already exists
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_domain
+ domain_type: vmm
+ vm_provider: vmware
+ state: absent
+
+ # CREATE VMWARE DOMAIN
+ - name: Create ansible_domain
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_domain
+ domain_type: vmm
+ vm_provider: vmware
+ state: present
+
+ # CREATE VMWARE UPLINK CONTAINER
+ - name: Create VMWare Uplink Container
+ aci_vmm_uplink_container:
+ <<: *aci_info
+ domain: ansible_domain
+ num_of_uplinks: 2
+ state: present
+ register: create_container
+
+ - name: Verify Uplink Container Creation
+ assert:
+ that:
+ - create_container.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont"
+ - create_container.current.0.vmmUplinkPCont.attributes.numOfUplinks == "2"
+ - create_container.current.0.vmmUplinkPCont.attributes.annotation == 'orchestrator:ansible'
+
+ # CREATE VMWARE UPLINK CONTAINER AGAIN TO CHECK IDEMPOTENCE
+ - name: Create VMWare Uplink Container again
+ aci_vmm_uplink_container:
+ <<: *aci_info
+ domain: ansible_domain
+ num_of_uplinks: 2
+ state: present
+ register: create_container_again
+
+ - name: Verify Uplink Container Creation Idempotence
+ assert:
+ that:
+ - create_container_again is not changed
+ - create_container_again.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont"
+ - create_container_again.current.0.vmmUplinkPCont.attributes.numOfUplinks == "2"
+
+ # MODIFY VMWARE UPLINK CONTAINER
+ - name: Update VMWare Uplink Container
+ aci_vmm_uplink_container:
+ <<: *aci_info
+ domain: ansible_domain
+ num_of_uplinks: 3
+ state: present
+ register: update_container
+
+ - name: Verify Uplink Container is updated
+ assert:
+ that:
+ - update_container is changed
+ - update_container.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont"
+ - update_container.current.0.vmmUplinkPCont.attributes.numOfUplinks == "3"
+
+ # QUERY VMWARE UPLINK CONTAINER
+ - name: Update VMWare Uplink Container
+ aci_vmm_uplink_container:
+ <<: *aci_info
+ domain: ansible_domain
+ state: query
+ register: query_container
+
+ - name: Verify Uplink Container Query
+ assert:
+ that:
+ - query_container is not changed
+ - query_container.current.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont"
+ - query_container.current.0.vmmUplinkPCont.attributes.numOfUplinks == "3"
+
+ # DELETE VMWARE UPLINK CONTAINER
+ - name: Remove Uplink Container
+ aci_vmm_uplink_container:
+ <<: *aci_info
+ domain: ansible_domain
+ state: absent
+ register: delete_container
+
+ - name: Verify Uplink Container removal
+ assert:
+ that:
+ - delete_container is changed
+ - delete_container.current == []
+ - delete_container.previous.0.vmmUplinkPCont.attributes.dn == "uni/vmmp-VMware/dom-ansible_domain/uplinkpcont"
+ - delete_container.previous.0.vmmUplinkPCont.attributes.numOfUplinks == "3"
+
+ # DELETE VMWARE UPLINK CONTAINER AGAIN TO TEST IDEMPOTENCE
+ - name: Remove Uplink Container again
+ aci_vmm_uplink_container:
+ <<: *aci_info
+ domain: ansible_domain
+ state: absent
+ register: delete_container_again
+
+ - name: Verify Uplink Container removal idempotence
+ assert:
+ that:
+ - delete_container_again is not changed
+
+ # CLEAN UP
+ - name: Remove ansible_domain
+ aci_domain:
+ <<: *aci_info
+ domain: ansible_domain
+ domain_type: vmm
+ vm_provider: vmware
+ state: absent
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_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_vmm_vswitch_policy/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml
new file mode 100644
index 000000000..371137af4
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_vswitch_policy/tasks/main.yml
@@ -0,0 +1,205 @@
+# Test code for the ACI modules
+# Copyright: (c) 2021, Anvitha Jain (@anvitha-jain) <anvjain@cisco.com>
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: '{{ aci_output_level | default("debug") }}'
+
+- name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+# Remove VMM domain
+- name: Remove VMM domain (normal mode)
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: '{{ item.domain }}'
+ domain_type: vmm
+ vm_provider: '{{ item.provider }}'
+ state: absent
+ register: nm_remove_domain
+ loop:
+ - { domain: 'vmm_dom', provider: 'vmware' }
+ - { domain: 'vmm_dom', provider: 'microsoft' }
+ - { domain: 'microsoft_dom', provider: 'microsoft' }
+
+- 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:
+ # ADD DOMAIN
+ - name: Add VMM domain
+ cisco.aci.aci_domain:
+ <<: *aci_info
+ domain: '{{ item.domain }}'
+ domain_type: vmm
+ vm_provider: '{{ item.provider }}'
+ state: present
+ register: nm_add_domain
+ loop:
+ - { domain: 'vmm_dom', provider: 'vmware' }
+ - { domain: 'vmm_dom', provider: 'microsoft' }
+ - { domain: 'microsoft_dom', provider: 'microsoft' }
+
+ - name: Verify VMM add_domain
+ assert:
+ that:
+ - nm_add_domain is changed
+
+ - name: Add a vSwitch policy to vmware domain
+ aci_vmm_vswitch_policy: &add_vmware_policies
+ <<: *aci_info
+ domain: vmm_dom
+ vm_provider: vmware
+ lldp_policy: LLDP_policy
+ cdp_policy: CDP_policy
+ port_channel_policy: PORT_Channel_policy
+ state: present
+ register: add_vmware_policy
+
+ - name: Verify VMM add_vmware_policy
+ assert:
+ that:
+ - add_vmware_policy is changed
+ - add_vmware_policy.previous == []
+ - add_vmware_policy.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont'
+ - add_vmware_policy.current.0.vmmVSwitchPolicyCont.children.0.vmmRsVswitchOverrideLacpPol.attributes.tDn == 'uni/infra/lacplagp-PORT_Channel_policy'
+ - add_vmware_policy.current.0.vmmVSwitchPolicyCont.children.1.vmmRsVswitchOverrideCdpIfPol.attributes.tDn == 'uni/infra/cdpIfP-CDP_policy'
+ - add_vmware_policy.current.0.vmmVSwitchPolicyCont.children.2.vmmRsVswitchOverrideLldpIfPol.attributes.tDn == 'uni/infra/lldpIfP-LLDP_policy'
+ - add_vmware_policy.current.0.vmmVSwitchPolicyCont.attributes.annotation == 'orchestrator:ansible'
+
+ - name: Add a vSwitch policy to vmware domain
+ aci_vmm_vswitch_policy:
+ <<: *add_vmware_policies
+ netflow_exporter:
+ name: Netflow_Exporter_policy
+ enhanced_lag:
+ - name: Enhanced_Lag_pol
+ state: present
+ register: add_vmware_policy_2
+
+ - name: Verify VMM add_vmware_policy_2
+ assert:
+ that:
+ - add_vmware_policy_2 is changed
+ - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont'
+ - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.children.0.lacpEnhancedLagPol.attributes.name == 'Enhanced_Lag_pol'
+ - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.children.1.vmmRsVswitchExporterPol.attributes.tDn == 'uni/infra/vmmexporterpol-Netflow_Exporter_policy'
+ - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.children.2.vmmRsVswitchOverrideLacpPol.attributes.tDn == 'uni/infra/lacplagp-PORT_Channel_policy'
+ - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.children.3.vmmRsVswitchOverrideCdpIfPol.attributes.tDn == 'uni/infra/cdpIfP-CDP_policy'
+ - add_vmware_policy_2.current.0.vmmVSwitchPolicyCont.children.4.vmmRsVswitchOverrideLldpIfPol.attributes.tDn == 'uni/infra/lldpIfP-LLDP_policy'
+
+ - name: Add MTU policy to vmware domain when version is >= 4.2
+ aci_vmm_vswitch_policy:
+ <<: *add_vmware_policies
+ mtu_policy: MTU_policy
+ state: present
+ register: add_vmware_mtu_policy
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+
+ - name: Verify VMM add_vmware_mtu_policy
+ assert:
+ that:
+ - add_vmware_mtu_policy is changed
+ - add_vmware_mtu_policy.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont'
+ - add_vmware_mtu_policy.current.0.vmmVSwitchPolicyCont.children.0.vmmRsVswitchOverrideMtuPol.attributes.tDn == 'uni/fabric/l2pol-MTU_policy'
+ when: version.current.0.topSystem.attributes.version is version('4.2', '>=')
+
+ - name: Add a vSwitch policy to microsoft domain
+ aci_vmm_vswitch_policy:
+ <<: *aci_info
+ domain: vmm_dom
+ vm_provider: microsoft
+ lldp_policy: ms_LLDP_policy
+ cdp_policy: ms_CDP_policy
+ port_channel_policy: ms_PORT_Channel_policy
+ state: present
+ register: add_microsoft_policy
+
+ - name: Verify VMM add_microsoft_policy
+ assert:
+ that:
+ - add_microsoft_policy is changed
+ - add_microsoft_policy.previous == []
+ - add_microsoft_policy.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-Microsoft/dom-vmm_dom/vswitchpolcont'
+ - add_microsoft_policy.current.0.vmmVSwitchPolicyCont.children.0.vmmRsVswitchOverrideLacpPol.attributes.tDn == 'uni/infra/lacplagp-ms_PORT_Channel_policy'
+ - add_microsoft_policy.current.0.vmmVSwitchPolicyCont.children.1.vmmRsVswitchOverrideCdpIfPol.attributes.tDn == 'uni/infra/cdpIfP-ms_CDP_policy'
+ - add_microsoft_policy.current.0.vmmVSwitchPolicyCont.children.2.vmmRsVswitchOverrideLldpIfPol.attributes.tDn == 'uni/infra/lldpIfP-ms_LLDP_policy'
+
+ - name: Add STP vSwitch policy to another microsoft domain
+ aci_vmm_vswitch_policy:
+ <<: *aci_info
+ domain: microsoft_dom
+ vm_provider: microsoft
+ stp_policy: ms_STP_policy
+ state: present
+ register: add_microsoft_stp_policy
+
+ - name: Verify VMM add_microsoft_stp_policy
+ assert:
+ that:
+ - add_microsoft_stp_policy is changed
+ - add_microsoft_stp_policy.previous == []
+ - add_microsoft_stp_policy.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-Microsoft/dom-microsoft_dom/vswitchpolcont'
+ - add_microsoft_stp_policy.current.0.vmmVSwitchPolicyCont.children.0.vmmRsVswitchOverrideStpPol.attributes.tDn == 'uni/infra/ifPol-ms_STP_policy'
+
+ - name: Query all the vSwitch policy
+ aci_vmm_vswitch_policy:
+ <<: *aci_info
+ state: query
+ register: query_all_vmware
+
+ - name: Query all the vSwitch policy of the VMWare domain
+ aci_vmm_vswitch_policy:
+ <<: *aci_info
+ state: query
+ register: query_all_microsoft
+
+ - name: Verify Query all tasks for vmware and microsoft domain
+ assert:
+ that:
+ - query_all_vmware is not changed
+ - query_all_microsoft is not changed
+
+ - name: Query vSwitch policies of VMWare domain
+ aci_vmm_vswitch_policy:
+ <<: *aci_info
+ domain: vmm_dom
+ vm_provider: vmware
+ state: query
+ register: query_vmware
+
+ - name: Verify Query vSwitch policy of the VMWare domain
+ assert:
+ that:
+ - query_vmware is not changed
+ - query_vmware.current.0.vmmVSwitchPolicyCont.attributes.dn == 'uni/vmmp-VMware/dom-vmm_dom/vswitchpolcont'
+
+ - name: Remove vSwitch Policy from VMware VMM domain
+ aci_vmm_vswitch_policy:
+ <<: *aci_info
+ domain: vmm_dom
+ vm_provider: vmware
+ state: absent
+ register: remove_vmware_vSwitch_policy
+
+ - name: Verify remove_vmware_vSwitch_policy
+ assert:
+ that:
+ - remove_vmware_vSwitch_policy is changed
+ - remove_vmware_vSwitch_policy.current == [] \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
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
new file mode 100644
index 000000000..fa3f1057c
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml
@@ -0,0 +1,192 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+- name: Test that we have an ACI APIC host, ACI username and ACI password
+ fail:
+ msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.'
+ when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined
+
+- name: ensure tenant exists for tests to kick off
+ cisco.aci.aci_tenant: &aci_tenant_present
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ output_level: debug
+ state: present
+ tenant: ansible_test
+ register: tenant_present
+
+- name: ensure vrf does not exist yet for tests to kick off
+ cisco.aci.aci_vrf:
+ <<: *aci_tenant_present
+ vrf: "{{ item }}"
+ state: absent
+ with_items:
+ - anstest
+ - anstest2
+
+- name: create vrf - check mode works
+ cisco.aci.aci_vrf: &aci_vrf_present
+ <<: *aci_tenant_present
+ vrf: anstest
+ description: Ansible Test
+ check_mode: true
+ register: vrf_present_check_mode
+
+- name: create vrf - creation works
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ register: vrf_present
+
+- name: create vrf again - idempotency works
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ register: vrf_present_idempotent
+
+- name: update vrf - update works
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ description: Ansible Test Update
+ policy_control_preference: unenforced
+ register: vrf_update
+
+- name: create another vrf - check more params
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ vrf: anstest2
+ policy_control_direction: egress
+ preferred_group: enabled
+ match_type: all
+ register: vrf_present_2
+
+- name: create vrf without all necessary params - failure message works
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ tenant: "{{ fake_var | default(omit) }}"
+ ignore_errors: true
+ register: vrf_present_missing_param
+
+- name: present asserts
+ assert:
+ that:
+ - vrf_present_check_mode is changed
+ - vrf_present_check_mode.sent.fvCtx.attributes.descr == 'Ansible Test'
+ - vrf_present_check_mode.sent.fvCtx.attributes.name == 'anstest'
+ - vrf_present is changed
+ - vrf_present.sent == vrf_present_check_mode.sent
+ - vrf_present.current.0.fvCtx.attributes.annotation == 'orchestrator:ansible'
+ - vrf_present.previous == []
+ - vrf_present_idempotent is not changed
+ - vrf_present_idempotent.previous != []
+ - vrf_update is changed
+ - vrf_update.previous != []
+ - vrf_update.sent != vrf_update.proposed
+ - vrf_update.sent.fvCtx.attributes.descr == 'Ansible Test Update'
+ - vrf_update.sent.fvCtx.attributes.pcEnfPref == 'unenforced'
+ - 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.children.0.vzAny.attributes.matchT == 'All'
+ - vrf_present_2.current.0.fvCtx.children.0.vzAny.attributes.prefGrMemb == 'enabled'
+ - vrf_present_missing_param is failed
+ - vrf_present_missing_param.msg == 'state is present but all of the following are missing{{":"}} tenant'
+
+- name: get all vrf
+ cisco.aci.aci_vrf: &aci_query
+ <<: *aci_tenant_present
+ state: query
+ tenant: "{{ fake_var | default(omit) }}"
+ register: query_all
+
+- name: get all in tenant
+ cisco.aci.aci_vrf:
+ <<: *aci_query
+ tenant: ansible_test
+ register: query_tenant
+
+- name: get all with name
+ cisco.aci.aci_vrf:
+ <<: *aci_query
+ vrf: anstest
+ register: query_vrf_vrf
+
+- name: get vrf
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_present
+ state: query
+ register: query_vrf
+
+- name: query asserts
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current | length > 1
+ - query_all.current.0.fvCtx is defined
+ - '"class/fvCtx.json" in query_all.url'
+ - query_tenant is not changed
+ - query_tenant.current | length == 1
+ - query_tenant.current.0.fvTenant.children | length == 2
+ - query_tenant.current.0.fvTenant.attributes.name == "ansible_test"
+ - '"rsp-subtree-class=fvCtx" in query_tenant.filter_string'
+ - '"tn-ansible_test.json" in query_tenant.url'
+ - query_vrf_vrf is not changed
+ - query_vrf_vrf.current != []
+ - query_vrf_vrf.current.0.fvCtx.attributes.name == "anstest"
+ - '"query-target-filter=eq(fvCtx.name,\"anstest\")" in query_vrf_vrf.filter_string'
+ - '"class/fvCtx.json" in query_vrf_vrf.url'
+ - query_vrf is not changed
+ - query_vrf.current | length == 1
+ - '"tn-ansible_test/ctx-anstest.json" in query_vrf.url'
+
+- name: delete vrf - check mode works
+ cisco.aci.aci_vrf: &aci_vrf_absent
+ <<: *aci_vrf_present
+ state: absent
+ check_mode: true
+ register: vrf_absent_check_mode
+
+- name: delete vrf - delete works
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_absent
+ register: vrf_absent
+
+- name: delete vrf again - idempotency works
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_absent
+ register: vrf_absent_idempotent
+
+- name: delete vrf - cleanup
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_absent
+ name: anstest2
+
+- name: delete vrf missing param - fails properly
+ cisco.aci.aci_vrf:
+ <<: *aci_vrf_absent
+ vrf: "{{ fakevar | default(omit) }}"
+ ignore_errors: true
+ register: vrf_absent_missing_param
+
+- name: asserts for deletion task
+ assert:
+ that:
+ - vrf_absent_check_mode is changed
+ - vrf_absent_check_mode.previous != []
+ - vrf_absent_check_mode.proposed == {}
+ - vrf_absent is changed
+ - vrf_absent.previous == vrf_absent_check_mode.previous
+ - vrf_absent_idempotent is not changed
+ - vrf_absent_idempotent.previous == []
+ - vrf_absent_missing_param is failed
+ - 'vrf_absent_missing_param.msg == "state is absent but all of the following are missing: vrf"'
+
+- name: delete tenant - cleanup before ending tests
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present is changed \ No newline at end of file
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/aliases b/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/aliases
new file mode 100644
index 000000000..209b793f9
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/aliases
@@ -0,0 +1,2 @@
+# No ACI simulator yet, so not enabled
+# unsupported
diff --git a/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml b/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml
new file mode 100644
index 000000000..65e6f1278
--- /dev/null
+++ b/ansible_collections/cisco/aci/tests/integration/targets/aci_vzany_to_contract/tasks/main.yml
@@ -0,0 +1,170 @@
+# Author: Marcel Zehnder (@maercu)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# 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") }}'
+
+# CLEAN ENVIRONMENT
+- name: Remove test tenant1 before we kickoff
+ cisco.aci.aci_tenant: &tenant1_absent
+ <<: *aci_info
+ tenant: ansible_test
+ state: absent
+
+- name: Remove test tenant2 before we kickoff
+ cisco.aci.aci_tenant: &tenant2_absent
+ <<: *aci_info
+ tenant: ansible_test_2
+ state: absent
+
+# SETUP ENVIRONMENT
+- name: Create tenant1
+ cisco.aci.aci_tenant: &tenant1_present
+ <<: *tenant1_absent
+ state: present
+
+- name: Configure source contract for cif
+ cisco.aci.aci_contract:
+ <<: *tenant1_present
+ contract: cifsrc
+
+- name: Create tenant2
+ cisco.aci.aci_tenant: &tenant2_present
+ <<: *tenant2_absent
+ state: present
+
+- name: Create VRF
+ cisco.aci.aci_vrf: &vrf_present
+ <<: *tenant2_present
+ vrf: vzanyvrf
+
+- name: Configure contract
+ cisco.aci.aci_contract:
+ <<: *tenant2_present
+ contract: '{{ item }}'
+ loop:
+ - testcp
+ - testcp2
+
+- name: Create contract interface in test tenant
+ cisco.aci.aci_contract_export:
+ <<: *tenant1_present
+ contract: cifsrc
+ destination_tenant: ansible_test_2
+ name: testcif
+
+# BEGIN WITH TESTS
+- name: Attach contract as provider to vzAny (check_mode)
+ cisco.aci.aci_vzany_to_contract: &prov_present
+ <<: *vrf_present
+ contract: testcp
+ contract_type: provider
+ check_mode: true
+ register: cm_vzany_prov
+
+- name: Attach contract as provider to vzAny (normal_mode)
+ cisco.aci.aci_vzany_to_contract:
+ <<: *prov_present
+ register: nm_vzany_prov
+
+- name: Verify vzany_prov
+ assert:
+ that:
+ - cm_vzany_prov is changed
+ - nm_vzany_prov is changed
+ - cm_vzany_prov.previous == nm_vzany_prov.previous == []
+ - cm_vzany_prov.sent.vzRsAnyToProv.attributes.tnVzBrCPName == nm_vzany_prov.sent.vzRsAnyToProv.attributes.tnVzBrCPName == 'testcp'
+ - nm_vzany_prov.current.0.vzRsAnyToProv.attributes.annotation == 'orchestrator:ansible'
+
+- name: Attach contract again, check if idempotency works
+ cisco.aci.aci_vzany_to_contract:
+ <<: *prov_present
+ register: add_prov_again
+
+- name: Verify add_prov_again
+ assert:
+ that:
+ - add_prov_again is not changed
+
+# ATTACH ANOTHER PROVIDER
+- name: Attach another contract as provider to vzAny
+ cisco.aci.aci_vzany_to_contract: &prov2_present
+ <<: *prov_present
+ contract: testcp2
+
+# ATTACH CONTRACT AS CONSUMER
+- name: Attach contract as consumer to vzAny
+ cisco.aci.aci_vzany_to_contract: &cons_present
+ <<: *prov_present
+ contract_type: consumer
+
+# ATTACH CONTRACT INTERFACE (AS CONSUMER)
+- name: Attach contract interface to vzAny
+ cisco.aci.aci_vzany_to_contract: &cif_present
+ <<: *prov_present
+ contract: testcif
+ contract_type: interface
+
+# QUERY ALL PROVIDERS
+- name: Query all providers
+ cisco.aci.aci_vzany_to_contract:
+ <<: *aci_info
+ state: query
+ contract_type: provider
+ register: query_all_provs
+
+- name: Verify query_all_provs
+ assert:
+ that:
+ - query_all_provs is not changed
+ - query_all_provs.current|length >= 2
+
+# QUERY A SPECIFIC CONTRACT BINDING
+- name: Query a specific binding
+ cisco.aci.aci_vzany_to_contract:
+ <<: *cons_present
+ state: query
+ register: query_spec_bind
+
+- name: Verify query_spec_bind
+ assert:
+ that:
+ - query_spec_bind is not changed
+ - query_spec_bind.current|length == 1
+
+# REMOVE ALL BINDINGS
+- name: Remove provider
+ cisco.aci.aci_vzany_to_contract:
+ <<: *prov_present
+ state: absent
+ register: del_prov
+
+- name: Remove consumer
+ cisco.aci.aci_vzany_to_contract:
+ <<: *cons_present
+ state: absent
+ register: del_cons
+
+- name: Remove interface
+ cisco.aci.aci_vzany_to_contract:
+ <<: *cif_present
+ state: absent
+ register: del_cif
+
+- name: Verify remove_intf
+ assert:
+ that:
+ - del_prov is changed
+ - del_cons is changed
+ - del_cif is changed
+ - del_prov.current == del_cons.current == del_cif.current ==[]
+ \ No newline at end of file