summaryrefslogtreecommitdiffstats
path: root/collections-debian-merged/ansible_collections/cisco/aci
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-14 20:03:01 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-14 20:03:01 +0000
commita453ac31f3428614cceb99027f8efbdb9258a40b (patch)
treef61f87408f32a8511cbd91799f9cececb53e0374 /collections-debian-merged/ansible_collections/cisco/aci
parentInitial commit. (diff)
downloadansible-a453ac31f3428614cceb99027f8efbdb9258a40b.tar.xz
ansible-a453ac31f3428614cceb99027f8efbdb9258a40b.zip
Adding upstream version 2.10.7+merged+base+2.10.8+dfsg.upstream/2.10.7+merged+base+2.10.8+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'collections-debian-merged/ansible_collections/cisco/aci')
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml171
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/.gitignore393
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/.vscode/settings.json3
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/CHANGELOG.rst130
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/FILES.json2938
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/LICENSE678
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/MANIFEST.json45
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/README.md91
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/changelogs/.gitignore1
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml444
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/changelogs/changelog.yaml102
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/changelogs/config.yaml31
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/meta/runtime.yml2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py120
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/aci.py1336
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user.py367
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user_certificate.py298
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py437
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py429
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py364
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep.py286
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_domain.py313
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_ap.py290
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd.py461
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_dhcp_label.py312
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_subnet.py467
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_to_l3out.py240
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_cidr.py292
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_ctx_profile.py318
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_provider.py178
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_region.py219
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py330
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_vpn_gateway.py253
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_zone.py233
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_rollback.py321
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py337
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract.py312
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject.py358
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_filter.py319
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain.py395
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_encap_pool.py378
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_vlan_pool.py366
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py316
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py449
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg.py398
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_monitoring_policy.py246
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py351
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_master.py302
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py441
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_node.py288
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_scheduler.py331
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter.py279
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter_entry.py376
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group.py238
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group_node.py248
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_policy.py253
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_source.py303
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_cdp.py266
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_fc.py240
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_l2.py265
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_breakout_port_group.py259
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py580
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_profile.py313
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py292
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_lldp.py248
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_mcp.py239
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_ospf.py405
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_channel.py322
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_security.py253
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_selector_to_switch_policy_leaf_profile.py254
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py320
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py310
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py367
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py309
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py346
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py332
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py340
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_route_tag_policy.py255
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py368
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group.py236
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py242
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_policy.py277
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_rest.py451
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_static_binding_to_epg.py441
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py349
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_leaf_profile.py250
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py304
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_system.py197
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_taboo_contract.py286
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant.py261
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py246
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_ep_retention_policy.py361
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_dst_group.py246
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group.py265
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group_to_dst_group.py260
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool.py283
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool_encap_block.py362
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vmm_credential.py316
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vrf.py324
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/.gitignore1
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/inventory.networking11
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/target-prefixes.network1
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml235
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt14
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.key16
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin_invalid.key3
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/openssh_rsa.key16
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key15
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt14
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key16
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml279
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml254
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml205
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml141
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml331
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml212
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml190
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml213
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml147
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml240
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml303
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml323
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml51
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml66
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml347
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml157
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml90
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml108
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml144
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml164
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml246
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml194
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml176
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml176
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml176
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml24
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml176
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml184
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml635
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml222
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml18
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml274
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vsan.yml16
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml178
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml18
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml387
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml20
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml19
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml187
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml254
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml202
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml279
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml217
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml223
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml299
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml207
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases1
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml106
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml162
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml453
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml266
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml285
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml231
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml171
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml154
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml129
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml156
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml145
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml210
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml120
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml138
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml191
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml166
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml156
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml28
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml167
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml148
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml148
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml206
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml142
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml213
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml213
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_system/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml63
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml289
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml261
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml303
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml15
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml303
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml384
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml12
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml250
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases2
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml191
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.10.txt0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.9.txt0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/requirements.txt4
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/builtins.py33
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/mock.py122
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/unittest.py38
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/loader.py116
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/path.py8
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/procenv.py90
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/vault_helper.py39
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/yaml_helper.py124
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/conftest.py74
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py386
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/utils.py52
-rw-r--r--collections-debian-merged/ansible_collections/cisco/aci/tests/unit/requirements.txt10
277 files changed, 50127 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml b/collections-debian-merged/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml
new file mode 100644
index 00000000..054c1808
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/.github/workflows/ansible-test.yml
@@ -0,0 +1,171 @@
+name: CI
+on:
+ push:
+ branches: master
+ pull_request:
+ schedule:
+ # * is a special character in YAML so you have to quote this string
+ - cron: '0 8 * * *'
+jobs:
+ build:
+ name: Build collection
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ ansible: [2.9.12, 2.10.0]
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v2
+
+ - name: Set up Python 3.7
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.7
+
+ - name: Install ansible-base (v${{ matrix.ansible }})
+ run: pip install https://github.com/ansible/ansible/archive/v${{ matrix.ansible }}.tar.gz --disable-pip-version-check
+
+ - name: Build a collection tarball
+ run: ansible-galaxy collection build --output-path "${GITHUB_WORKSPACE}/.cache/collection-tarballs"
+
+ - name: Store migrated collection artifacts
+ uses: actions/upload-artifact@v1
+ with:
+ name: collection
+ path: .cache/collection-tarballs
+
+ sanity:
+ name: Sanity in ubuntu-latest
+ needs:
+ - build
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ ansible: [2.9.12, 2.10.0]
+ steps:
+ - name: Set up Python 3.7
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.7
+
+ - name: Install ansible-base (v${{ matrix.ansible }})
+ run: pip install https://github.com/ansible/ansible/archive/v${{ matrix.ansible }}.tar.gz --disable-pip-version-check
+
+ - name: Install coverage (v4.5.4)
+ run: pip install coverage==4.5.4
+
+ - name: Download migrated collection artifacts
+ uses: actions/download-artifact@v1
+ with:
+ name: collection
+ path: .cache/collection-tarballs
+
+ - name: Install the collection tarball
+ run: ansible-galaxy collection install .cache/collection-tarballs/*.tar.gz
+
+ - name: Run sanity tests
+ run: ansible-test sanity --docker -v --color --truncate 0 --coverage
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
+
+ - name: Generate coverage report
+ run: ansible-test coverage xml -v --requirements --group-by command --group-by version
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
+
+ - name: Push coverate report to codecov.io
+ run: bash <(curl -s https://codecov.io/bash) -s 'tests/output/reports/' -F integration
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
+
+ units:
+ name: Units in ubuntu-latest
+ needs:
+ - build
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ ansible: [2.9.12, 2.10.0]
+ steps:
+ - name: Set up Python 3.7
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.7
+
+ - name: Install ansible-base (v${{ matrix.ansible }})
+ run: pip install https://github.com/ansible/ansible/archive/v${{ matrix.ansible }}.tar.gz --disable-pip-version-check
+
+ - name: Install coverage (v4.5.4)
+ run: pip install coverage==4.5.4
+
+ - name: Download migrated collection artifacts
+ uses: actions/download-artifact@v1
+ with:
+ name: collection
+ path: .cache/collection-tarballs
+
+ - name: Install the collection tarball
+ run: ansible-galaxy collection install .cache/collection-tarballs/*.tar.gz
+
+ - name: Run unit tests
+ run: ansible-test units --docker -v --color --truncate 0 --python 3.7 --coverage
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
+
+ - name: Generate coverage report.
+ run: ansible-test coverage xml -v --requirements --group-by command --group-by version
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
+
+ - uses: codecov/codecov-action@v1
+ with:
+ fail_ci_if_error: false
+ file: /home/runner/.ansible/collections/ansible_collections/cisco/aci/tests/output/reports/coverage.xml
+
+ integration:
+ name: Integration in ubuntu-latest
+ needs:
+ - build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Set up Python 3.7
+ uses: actions/setup-python@v1
+ with:
+ python-version: 3.7
+
+ - name: Install ansible-base (v2.9.12)
+ run: pip install https://github.com/ansible/ansible/archive/v2.9.12.tar.gz --disable-pip-version-check
+
+ - name: Install coverage (v4.5.4)
+ run: pip install coverage==4.5.4
+
+ - name: Download migrated collection artifacts
+ uses: actions/download-artifact@v1
+ with:
+ name: collection
+ path: .cache/collection-tarballs
+
+ - name: Install the collection tarball
+ run: ansible-galaxy collection install .cache/collection-tarballs/*.tar.gz
+
+ - name: Requesting integration mutex
+ uses: nev7n/wait_for_response@v1
+ with:
+ url: ${{ format('https://8v7s765ibh.execute-api.us-west-1.amazonaws.com/v1/ansible-aci?repo={0}', github.repository) }}
+ responseCode: 200
+ timeout: 2000000
+ interval: 5000
+
+ - name: Run integration tests on Python 3.7
+ run: ansible-test network-integration --docker -v --color --retry-on-error --python 3.7 --truncate 0 --continue-on-error --coverage
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
+
+ - name: Releasing integration mutex
+ uses: nev7n/wait_for_response@v1
+ if: always()
+ with:
+ url: ${{ format('https://8v7s765ibh.execute-api.us-west-1.amazonaws.com/v1/ansible-aci/release?repo={0}', github.repository) }}
+ responseCode: 200
+
+ - name: Generate coverage report
+ run: ansible-test coverage xml -v --requirements --group-by command --group-by version
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
+
+ - name: Push coverate report to codecov.io
+ run: bash <(curl -s https://codecov.io/bash) -s 'tests/output/reports/' -F integration
+ working-directory: /home/runner/.ansible/collections/ansible_collections/cisco/aci
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/.gitignore b/collections-debian-merged/ansible_collections/cisco/aci/.gitignore
new file mode 100644
index 00000000..2ee73b45
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/.gitignore
@@ -0,0 +1,393 @@
+
+# Created by https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
+# Edit at https://www.gitignore.io/?templates=git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
+
+### dotenv ###
+.env
+
+### Emacs ###
+# -*- mode: gitignore; -*-
+*~
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+*.elc
+auto-save-list
+tramp
+.\#*
+
+# Org-mode
+.org-id-locations
+*_archive
+
+# flymake-mode
+*_flymake.*
+
+# eshell files
+/eshell/history
+/eshell/lastdir
+
+# elpa packages
+/elpa/
+
+# reftex files
+*.rel
+
+# AUCTeX auto folder
+/auto/
+
+# cask packages
+.cask/
+dist/
+
+# Flycheck
+flycheck_*.el
+
+# server auth directory
+/server/
+
+# projectiles files
+.projectile
+
+# directory configuration
+.dir-locals.el
+
+# network security
+/network-security.data
+
+
+### Git ###
+# Created by git for backups. To disable backups in Git:
+# $ git config --global mergetool.keepBackup false
+*.orig
+
+# Created by git when using merge tools for conflicts
+*.BACKUP.*
+*.BASE.*
+*.LOCAL.*
+*.REMOTE.*
+*_BACKUP_*.txt
+*_BASE_*.txt
+*_LOCAL_*.txt
+*_REMOTE_*.txt
+
+#!! ERROR: jupyternotebook is undefined. Use list command to see defined gitignore types !!#
+
+### Linux ###
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### PyCharm+all ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### PyCharm+all Patch ###
+# Ignores the whole .idea folder and all .iml files
+# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
+
+.idea/
+
+# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
+
+*.iml
+modules.xml
+.idea/misc.xml
+*.ipr
+
+# Sonarlint plugin
+.idea/sonarlint
+
+### pydev ###
+.pydevproject
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# pyenv
+.python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# Mr Developer
+.mr.developer.cfg
+.project
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+### Vim ###
+# Swap
+[._]*.s[a-v][a-z]
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+
+# Session
+Session.vim
+Sessionx.vim
+
+# Temporary
+.netrwhist
+# Auto-generated tag files
+tags
+# Persistent undo
+[._]*.un~
+
+### WebStorm ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+
+# Generated files
+
+# Sensitive or high-churn files
+
+# Gradle
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+
+# Mongo Explorer plugin
+
+# File-based project format
+
+# IntelliJ
+
+# mpeltonen/sbt-idea plugin
+
+# JIRA plugin
+
+# Cursive Clojure plugin
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+
+# Editor-based Rest Client
+
+# Android studio 3.1+ serialized cache file
+
+### WebStorm Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator/
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# End of https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
+
+# vsCode
+.vscode
+
+# Ansible Collection tarball
+cisco-aci-*.tar.gz \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/.vscode/settings.json b/collections-debian-merged/ansible_collections/cisco/aci/.vscode/settings.json
new file mode 100644
index 00000000..76aa33c1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "python.pythonPath": "aci_3.8/bin/python"
+} \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/CHANGELOG.rst b/collections-debian-merged/ansible_collections/cisco/aci/CHANGELOG.rst
new file mode 100644
index 00000000..3f0628bc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/CHANGELOG.rst
@@ -0,0 +1,130 @@
+==========================================
+Cisco ACI Ansible Collection Release Notes
+==========================================
+
+.. contents:: Topics
+
+
+v1.1.1
+======
+
+Release Summary
+---------------
+
+Release v1.1.1 of the ``cisco.mso`` collection on 2020-11-23.
+This changelog describes all changes made to the modules and plugins included in this collection since v1.1.0.
+
+Minor Changes
+-------------
+
+- Add test file for aci_domain_to_encap_pool
+- aci_epg_to_domain moving child configs & classes to each domain type
+
+Bugfixes
+--------
+
+- Fix galaxy import warnings
+- Fix sanity issue in aci_epg_to_domain
+
+v1.1.0
+======
+
+Release Summary
+---------------
+
+Release v1.1.0 of the ``cisco.mso`` collection on 2020-10-30.
+This changelog describes all changes made to the modules and plugins included in this collection since v1.0.1.
+
+Minor Changes
+-------------
+
+- Ability to add monitoring policy to epgs and anps
+- Add Ansible Network ENV to fallback
+- Add aci_l3out_external_path_to_member.py & aci_l3out_static_routes modules
+- Add env_fallback for common connection params
+- Add env_fallback for the rest of the argument spec
+- Add new Subclass path support
+- Add new module and test file for leaf breakout port group
+- Added failure message to aci_interface_policy_leaf_policy_group
+- Update README.md
+- Update inventory
+- aci_epg_to_domain addition of promiscuous mode (#79)
+- aci_interface_policy_port_security addition of attribute:timeout (#80)
+
+Bugfixes
+--------
+
+- Existing_config variable is not reset during loop
+- Fix galaxy import warnings
+- Fix how validity of private key/private key file is checked to support new types
+- Fix incorrect domain types in aci_domain_to_encap_pool module
+
+v1.0.1
+======
+
+Release Summary
+---------------
+
+Release v1.0.1 of the ``cisco.mso`` collection on 2020-10-13.
+This changelog describes all changes made to the modules and plugins included in this collection since v1.0.0.
+
+Minor Changes
+-------------
+
+- Enable/Disable infra vlan in aci_aep and its test module
+- Set scope default value in aci_l3out_extsubnet
+
+Bugfixes
+--------
+
+- Fix convertion of json/yaml payload to xml in aci_rest
+- Fix dump of config for aci_rest
+- Fix issue of "current" in firmware_source module
+- Fix sanity issue in aci_rest and bump version to v1.0.1
+
+v1.0.0
+======
+
+Release Summary
+---------------
+
+This is the first official release of the ``cisco.aci`` collection on 2020-08-18.
+This changelog describes all changes made to the modules and plugins included in this collection since Ansible 2.9.0.
+
+
+Minor Changes
+-------------
+
+- Add Fex capability to aci_interface_policy_leaf_profile, aci_access_port_to_interface_policy_leaf_profile and aci_access_port_block_to_access_port
+- Add LICENSE file
+- Add aci_epg_to_contract_master module
+- Add annotation attribute to aci.py and to doc fragment.
+- Add annotation to every payload and add test case for annotation.
+- Add changelog
+- Add collection prefix to all integration tests
+- Add galaxy.yml file for collection listing
+- Add github action CI pipeline
+- Add module and test file for aci_bd_dhcp_label
+- Add modules and test files for aci_cloud_ctx_profile, aci_cloud_cidr, aci_cloud_subnet and aci_cloud_zone
+- Add modules and test files for aci_l2out, aci_l2out_extepg and aci_l3out_extepg_to_contract
+- Add names to documentation examples for modules from community.network
+- Add preferred group support to aci_vrf
+- Add support for Azure on all cloud modules
+- Add support for output_path to allow dump of REST API objects
+- Add support for owner_key and owner_tag for all modules and add test case for it.
+- Add vpn gateway dedicated module and remove vpn_gateway from cloud_ctx_profile module
+- Fix M() and module to use FQCN
+- Initial commit based on the collection migration available at "ansible-collection-migration/cisco.aci" which contains the ACI module from Ansible Core
+- Move aci.py to base of module_utils and fix references
+- Move test file to root of tests/unit/module_utils
+- Update Ansible version in CI and add 2.10.0 to sanity in CI.
+- Update Readme with supported versions
+- Update to test files to make the tests work on both 3.2 and 4.2.
+
+Bugfixes
+--------
+
+- Fix sanity issues to support 2.10.0
+- Fix some doc issues for a few modules
+- Fix some formatting issues (flake8) in unit tests.
+- Fixing integration tests and sanity. Tested on ACI 4.2(3l).
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/FILES.json b/collections-debian-merged/ansible_collections/cisco/aci/FILES.json
new file mode 100644
index 00000000..085cea69
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/FILES.json
@@ -0,0 +1,2938 @@
+{
+ "files": [
+ {
+ "name": ".",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "LICENSE",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1c38eb11b6b8cd591aed90793ca80bd3c499393f207b96640ddfa571f61f7b4f",
+ "format": 1
+ },
+ {
+ "name": "plugins",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/doc_fragments",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/doc_fragments/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/doc_fragments/aci.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ce1eba18a30f6906c18c834b271d9ee36b064697885e083fc1f0a2e3d51022ad",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/aci.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f354e6dc6fd808d4d7ace041cfbab7136f6787e846a59e1050f4db4fbec3e81a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l2out.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3c1f007283369e47a9b2dbd8c9dfb2f9a94a48f9285035cad4286c094b31796d",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_vlan_pool.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8d065c55b8d6bee3fe61538d6c7118a5d93ce76025b0ef76fcbee063daea74e3",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_domain_to_encap_pool.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ab41cc631460014f0b4ac1d34fc8b106aef641b997383e51d235ce220811c500",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_tenant_span_src_group_to_dst_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "695e6e52d0d44f86dbc3ebe829c4396b9a4d896bcbef1dcac34f8d0d797d65fa",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_domain_to_vlan_pool.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "588e692945d98acf13d7dbc26eeae170cff1ef83aebe02d9926cd160bd7c8e72",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l3out_extsubnet.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "de51d3411dc447cee6e3a0860f43308885986f3d17368a6c6560145ab17641c5",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l3out_static_routes.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b88228b4e5cada88f0606a023177d6196bd5b605e93db1229f6f8ecc229e2915",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_epg.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7cd2f9ee8b0b50998249d4f49ec8b4f25593b354fcc7ec35643ad62ec2e2a049",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_cloud_subnet.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "48b2a95ff5087918c7ae3d1b36cf274efc868b247918ddb5674308c3295045a3",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_aep_to_domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "575e2872b0a6aac9545cb75354f1565ad15372f407c062b303d598d927d04166",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_aaa_user_certificate.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "27e514fbb89ba01365db8b0094275375985829367dddddcdb36391062004083a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_firmware_group_node.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "095207bd3f72dcf32638922578d3ad31e77a731e667ca91efcc8df027af4b307",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_filter.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b3cda6a2a0aefe84a256b8e01fd06f1e7753ca1d3f8db6a5a02f7d775ec59061",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_config_snapshot.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0046490d4a19dfb2bb0b20be256e8952fbaf0b31e275b262ce392d4219e89549",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_epg_to_contract_master.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "efe1f84425d5831c82ec0986504081fa4fcfb7c6982c2c0c42bc7c78f873248e",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_lldp.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fd31cf864e4d8ff9cfb3fd0e51d0aa8e9acd9d4cae59cc4f63d679509bc950b3",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_port_security.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8e0b9a3c9a05439d0cf4dcb2b728853268dbaeaa96c2b327e8f6c6d8f61bd5de",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_tenant_span_src_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "376d583433dea1741ba2daf84eaa713013f1e9a6070a46ed0835e846c237820e",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_static_binding_to_epg.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ca35e7fe3132341b2346da7f9dc65823d6beb72562a0a777259c5142d3a95e8a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_contract_subject.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "be0097f6cdeae3f29d214dea14032bbb68bf3329f747b12200ac01d3b57b5adb",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_l2.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "609aa622d863ba996eda0ad74707a33a7bc43a62410e5de8a18b46c931164fbf",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_cloud_provider.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d6a731ad325068e4813bd8859e1b517f2a49ee79487b260b130667bb2c486f62",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_filter_entry.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e7dff4086b1415e9f63f34286c77123c5f0123251464debd22de8a2f117344f6",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_vrf.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d813b37cef2680264a09c11d8e0eea504a1ed8b80a1b0ea87813d8ac27fd5eda",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_leaf_profile.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0be99340ce8d2e2604da3e55ef97e608f2a5a5e4e6e6f073365988ce8e8eaede",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l3out.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9167ec5b6d509536548bb34d7848c341592b2521d0dc694b850dd0e2d5903fe6",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_fc.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "664865e0683cc6607959a2da1858088da6bae01645003efb09b8221b0000409c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_link_level.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bbbbd6ba28668c4030d00b37f6ae34c75ce4676a37c4223a9ecb5979d288a700",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_switch_policy_vpc_protection_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "86004a3da639ba800c566cf57108a7d41212d7f0394e3567581a0cdc37adc8f0",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_tenant_action_rule_profile.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0bf64c679529b9663b56c09e75b8bd1bf71f6ddbb72c0da4555d49a10b9c432a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_leaf_breakout_port_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0b11f0e91043c6f6765150618c656098eb5e280297da31948f11cc7d2dbb6977",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_mcp.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9c2615487ddf26c6e694cac5e0183781f09d8a7d2c0cffa1a23864863c268f7b",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_maintenance_policy.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b74cef04324c1d086590507679b810369b63c54b12332f069cc946c27404257d",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_cloud_vpn_gateway.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9562e2f407f6e5a501f0bc0dbca115b4b3f336f8931c8b2d08c634821df0bdcd",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_cloud_cidr.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f27c5b956d7dc1fb6b157e8ba6e208f1018ff62195645cb19cbea21b62b64a4e",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_ap.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "90230741a96a0e6981a04d20d9acbf125a75aaf3a5962ee995246dbab5a6a1a4",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_tenant_span_dst_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "80dc907e9807583ed88e7efb234e3e6d9ab8cea0f2ef43857dfb90d00472621a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_taboo_contract.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4a3925936cfba0f2b8744987288eb5a648449162ee65c5880e12a4e79367b84e",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_contract.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "49b727ed24577161054da66ec4792bbe86226d247a752bddc15c929259e73218",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_fabric_node.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "95a08f9eb724433591732ad7f27939c8ed95b88d0bb7a4b4fbcfb25cd873d94d",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_firmware_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "24d62ab8356e6bf6ad4dc5a91b33abd5075168b2f83f6eb4721f06558aabc1dd",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_firmware_policy.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6669e6641be20f7facdcce1b2607559fd9150c91e453d8d08ba463c9e654b22b",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_ospf.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5f83137ba4c5804bf3273616cfb97f7f04e63095de18cb9a6907ad2193e4dcdc",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_epg_to_contract.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "cb1827a32607cb67d9cd7f6ccbf574673ecaec0ffc189637a549a04318bcf038",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_cloud_region.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fe30f345a9eb00e13b035d205e5b58422feb52f68694638d87f51ded691a3914",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_encap_pool_range.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8e970c136a2ac2a24f4447097ec6c42883ba495d0b476f3146e02fee0755ad53",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_switch_policy_leaf_profile.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2ad6ba100355c8a9d37e9ae302476c06c150f2833292823a212f1d9e3e90c512",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_vlan_pool_encap_block.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "59dec9619780eb596bf9e3e859dfd48377e250f31092e54c5acfc1dcfb58d940",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_system.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f0e0d492601df84d88933d6656827afa9625333add0eb0054a1e112b673a6242",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_maintenance_group_node.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "450452e406acc8b838595da5bacf6e7148ee908f847ba7f0f95821ccb88dc3c9",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_maintenance_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2f42e4204734a163a7efdb5d6d613da665d5d41d70261c4353e7a5b8c34ad584",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_selector_to_switch_policy_leaf_profile.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "73cf9ec9088029ed3f0a408fc10ab163e09280e74e4a3d6a876b6225ff62f0f5",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_access_sub_port_block_to_access_port.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c4c6b1cf6e53dc6f63f93ecf7d81ada7d4c7893966ec27b73287de2c7d16fe81",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_bd_subnet.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "881aee018ed6793b3e38cf8d9b28679bb84ae5e68290ec5a4894724c09c8a62b",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_cloud_zone.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "24daa0d08e06f8c971fa570236f8f8b69a690c6a84494923b90d4217fb22c3ad",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_encap_pool.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6537e8b5a578c985a17af3cde6af5523e7c98a6670d2bdfa725a328c91fc36b5",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_contract_subject_to_filter.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5f88c18f09502755c243e30f16acd72b2165971eb623d7c1b953f3d2a798191c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b2b7794f5e416221d90a531a7afadcca0bdb05c046014646ab28f2db0c0907f5",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3c274650a08c47c1776c8609726aa43f8f05f6c7a1dae27f9ecd0d2441516413",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_cdp.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1daf11c03d58f973cf789c7f1db8ba9cf2e159f5a7e5ac10cbff92faaea1e2dd",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l3out_extepg_to_contract.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "518fd244082eb28bfa62ed9aac65f5aac18347cd4db8bc632f0bab4a736799ea",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_config_rollback.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "dbcde141d3c9a58fa4d6fa5482a89a4584ca812fc842e086678effb1ff6bd665",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_tenant_ep_retention_policy.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f12ea0188dbbde492407dfecf44f776d0e0c03eb2a2740766d9921b0fb0b233a",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_access_port_block_to_access_port.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4ed9b58daa467df5dbf2fe51bdbfe5d7a78f5bc0c2203180debad9a2cbc09892",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_bd_to_l3out.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "eced4bb8c951f33637d8876cf7581b604abe81c008b2210db06e5514af863fa8",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_rest.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8a08598d8442f7c14c44e32cfa47ff2ca38212901420b8edbe1f791fe2c3571d",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l3out_logical_interface_vpc_member.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fa4459f3bf78bf8cb2f6d86b7bfe23cb7a89f298be73c4b3ed1f9872195187bd",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_tenant.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1111e3d2319085161e60d6deee53bb618c06bac99440050f734f4af11feef580",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_leaf_policy_group.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "826e77222521083e0efca1cc41185133ff71b26a5551e7954172689c53da14a9",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_aaa_user.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "837daf6aa51e584c5b6d90b980ea53f4ade47836583aa8b3864e978a6af97138",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_fabric_scheduler.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ff038cb757cea8fec85fc149082ac928c4eb7158c82ea7a94db3c85ed8a48b2c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_aep.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "46570b0ec5b85f6dae90d03636a29b0bea2f40b79a6e2d17aaaffc9dea559a1b",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l3out_extepg.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5b07dc084c7a195038e6814f664852274481994a1a0787b63c350473775dcf7e",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_epg_monitoring_policy.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7e83a903f88c38527d34558acf33f94468ca1dd1fa9717771b354f30f2210082",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_interface_policy_port_channel.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "06ce40cedba107ecb76c95f6717b2ea26d0d2649c471a630026a9c8d90e2c43c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l2out_extepg.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e9acbbe8c83458217796b180abf57008add4e49c76973173ba63b6bc67382608",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_l3out_route_tag_policy.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "74d9093f97947e13ac4f199f6be7f880cdde94a00869e189813bac851f876e52",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_epg_to_domain.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6d33e15e8443abaa652ef9592bb52f7e2be28e0fc2ec815a529e617d1833d888",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_cloud_ctx_profile.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a1ba83faa33cd570bbc8a938982ed1f8bf00a725f5c0253de95acd9cd3a7d56c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_bd.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "273515aa9bb78792d59bba83d6fdfad9e81225613634f94e3ea64300c5fcc3cf",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_bd_dhcp_label.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "234e6c848c64b3377f244575b3db0f9cd7b4d18e0c26e22ab70527ee25f52cb0",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_vmm_credential.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b1d714a256c6ab0434c1f47f2d86d346d2c826f08cadb3fea2ed9cebd6a42c0c",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_firmware_source.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "afae46ca8450a352216c6ce2935e348850ca6d418f67d1ddefad30ba2cd7c054",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/aci_switch_leaf_selector.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "edbd55df9c4d0e33215e237d96811c35c7adcc460c7f1df7b61eb2afc1e6d80c",
+ "format": 1
+ },
+ {
+ "name": "tests",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat/unittest.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5401a046e5ce71fa19b6d905abd0f9bdf816c0c635f7bdda6730b3ef06e67096",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat/builtins.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0ca4cac919e166b25e601e11acb01f6957dddd574ff0a62569cb994a5ecb63e1",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat/mock.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0af958450cf6de3fbafe94b1111eae8ba5a8dbe1d785ffbb9df81f26e4946d99",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "09c75b1b3fadff6870584617f4f178e168a23d4e0fb3187d7b100ffc8d4dbb68",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/vault_helper.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4535613601c419f7d20f0c21e638dabccf69b4a7fac99d5f6f9b81d1519dafd6",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/procenv.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "340adca3524b64ea1804b1be207cd86bba734e104b713bfe54852a20643aa07f",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/loader.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c45064a0beb765cd0b6cfbb74ca0cd491ceed2f4c2d22808f60a57071d9712cc",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/yaml_helper.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fada9f3506c951e21c60c2a0e68d3cdf3cadd71c8858b2d14a55c4b778f10983",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/path.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "359e469f24b220034c278a24eb121934afee992b427083eba2b34dfcd8ab1597",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/module_utils",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/module_utils/conftest.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "96375dffba3a180868fdd4038a2308c0b7096cd7dfcab3d9b1a99f9c3aa412e1",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/module_utils/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/module_utils/test_aci.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "768b3fed741cf5685a4fde97bb61b7f3d621214bdf8d16a3486506e0e168e045",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/utils.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "778c223e9618499416ec085116566f93e446298b40de0e97179e07a58353c353",
+ "format": 1
+ },
+ {
+ "name": "tests/integration",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_firmware_source",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_firmware_source/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_firmware_source/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "95ee636c739d032edc8dea1c14cb802c49f4bfd34b3bb2b0c2095390d35b4259",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_firmware_source/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_block_to_access_port",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_block_to_access_port/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "302595aa86e1ba3434fa3b62a5a67d7ff313cf4b66d6a2985c7cf00b9f70df86",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_block_to_access_port/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "17613562e9afcee2a22a3561fb48d712bb11d2c75cdc943e3f579243002fbfcb",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter_entry",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter_entry/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter_entry/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ec89c0177c4aef8eeb8cc6a9fa86ccbae363e74b15b0f93904367d41a6b7bd10",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter_entry/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool_encap_block",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool_encap_block/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "75de5c4fc7645577b679e2f19cf9e7d8c52b419ace18f4f2337171b4f02cbebf",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool_encap_block/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "48460744b70367fdb873c13664c6f84baa3a6897b37d48a863233fce20aa7671",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool/tasks/static.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "444e2593c90eac02ddd8f07369bb78a237dba0cafc94f099d5ea6e6a26e613ed",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e76d7fb454bd723c8d50d843592740a7ccd9c55be5adca9696e58f87fcb61915",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vlan_pool/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_encap_pool",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_encap_pool/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1844a85615bd16d2bec3d8eb61f04466c3b577879a7641a31922709a97f020f9",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_encap_pool/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3851edfac41a945b9f385dc13fa3fd17d86ad69a5cda1f05270ac6b3af779a4e",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6c86383d15c5ed0e2ca4b19fa79985fe774ae3ca967b524bfdc977b6981a8ba5",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_vpn_gateway",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_vpn_gateway/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3b8e50d44778469f24eeb06adbf0e81b38549a9be2b78e4be7fe2cd23530db7f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_vpn_gateway/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "69eb8ee842de7a9d5c5a5d8205a6cea9f96d9c6853bb9c4273cd47990d90b0ff",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_snapshot",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_snapshot/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_snapshot/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9421728c55bcc8e0b4ced96f918cd211818ac18d6bcdfe60ecd814cb619425a4",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_snapshot/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9d5ef7fdf45d2ad149fc8755388332bf48ada02be873c84efc4d11b0a9ef1c4b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_ap",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_ap/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_ap/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "636337667a8e39effe478991b00879375187a0c94c6ddb8998894443230ce90a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_ap/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_subnet",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_subnet/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_subnet/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5d264e7f48fdff018bf886edf3f3d9a5fe7b523c55fd1b835f9154037cdff393",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_subnet/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3b8e1e7ca5d0e43b23de7430700dd50360d1f4f8f40a3cb4e910d4d17cba3c29",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d88f7cfa27b684113ed401b53f6a68c7902bd923b76a38037cde17012d63e851",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extepg_to_contract",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extepg_to_contract/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e31a115146e45d490d640c244a07e479e2f38fddd1a4edcf9e23c465d21d86d8",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extepg_to_contract/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_taboo_contract",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_taboo_contract/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_taboo_contract/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "53e04e56771d3b74a5b672935be3e8466768e334399499a9b9f625e81b1fd6ab",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_taboo_contract/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_vlan_pool",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_vlan_pool/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6a129f9b4b6cccccfd27b7820c01b674d875379b635238fac2fd73eb320665be",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain_to_vlan_pool/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_domain",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_domain/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_domain/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c2cf8fcae73240916ddb1c7fafc117b49969fcac17cac6b2a3efb8445d3e80e1",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_domain/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_cdp",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_cdp/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "28d97d22d9d57fe3eea01812765d6d0fa5d0da24ffea67107a0b46ca6f8086fd",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_cdp/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7e5f1f59656b5c296b78849e4845810f74bbe10151203a6d224474a31f470f3f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_tenant",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_tenant/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_tenant/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b14d80fb154ad98992b0a6a0c7a1cce018f87d50afdf524699d8439941817f55",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_tenant/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "95ab6919b4c83c6e7be692c372d4c57c982accec8b50f080f16f642c1f90d0a9",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_link_level",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_link_level/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b055b73ed42cf465ff92d17a7d30487af202c192ca67366968880534c7317be1",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_link_level/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extsubnet",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extsubnet/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3be8b756d85fc8dc8b72ccb506bf3e9cad396698ae65b85e0ec1be5708709e1a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_extsubnet/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7f4423a6bdeeebdb16684343d744d83bb07c734ef5e6138f97b4d54fccfd0ba9",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/tasks/vmm-vmware.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "959a617c0be88f33096cb1942485f8545bf0c26302eb42d2af560c98d6526d39",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/tasks/l2dom.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "703e40fb6d8eacdee5ac7895835a8f15e07c569aa13fe5dda0ee034020bbf702",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/tasks/fc.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e7adac87a2d6a985a3912607cc2ee38f1b79c817bf30e7b30ee0a69bc7bbe3f7",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/tasks/phys.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a3d37b1db065366bdee6ca7c977129eb278390171bce9c3cf50fd73cacd7e3ef",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8094a133d927bf97b43ccdc714c7b8b962af676a11e616f205f21e605f27f1e9",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/tasks/l3dom.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "70bf07065aee2ddb867e2c2edb238d17fead70d369b776ce7f0973793995aa02",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_domain/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "39737fc5e285966c703f3918665cca13e2032452ab8bb537770649d77130e5d1",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_profile",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_profile/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "309e9c7d77e445bbde896d1e69ae9302bf25370958d3dc233a231af803de1ca3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_leaf_profile/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_fabric_node",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_fabric_node/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_fabric_node/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4bf934fa7834ad085caa3817a50559bd17d536b2967e0d823602510616d53e45",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_fabric_node/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep_to_domain",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep_to_domain/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep_to_domain/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9c324d2cbfc8fce8e1793e38d1b7fd3f5d003793db2c4f82d5da0418a78c3f8c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aep_to_domain/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool_range",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool_range/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b465efdc08e1e1a1a14290d23b5577dc5715fde6e1cba402d0312b3ef61f8a17",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8fc7481d36c2521ddec7b606520d1800ecac3f76bc0f8bac6c56e1bdee5f7e8e",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9a6dfeec5aa6516e733189aa6d28b0e6ef8876f23c173fb75079a2b7d6466f8c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool_range/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5db109efeefd874fc7bf1d2a065a9486de6e4f425ad1aa4d05b991d0e3b4ea1c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool_range/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_ospf",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_ospf/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8654a33e0a398c7ff6952476008457903409186552e9ac1d3d19d3e65df3286d",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_ospf/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_provider",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_provider/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_provider/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "688bf2fd96a6cdafac44d492e9a87baeb9ba099ebab9f2c859d25717ca056dae",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_provider/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c8b190f24432bcb398a73cc0b133fb50b36e1bec6eb9c0b4fa4e7797535d54fd",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract_master",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract_master/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4fae553fe3fa2dea6fd434d77b0ba9520e9d0366be1dd60f4b0f17b8668b96e3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg_to_contract_master/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_subnet",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_subnet/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_subnet/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "eb13dc900d536786df7b30a0097acd5bb93f1da9e777e49f6d6d202a4b35ed16",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_subnet/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vrf",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vrf/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vrf/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5121d7b9dc6e3596602cbb61b7276a27eb8e65456e8a197112c821079c08145b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vrf/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8266681c02afd2fe0727d5b9b9cdad65d9d3e6839050cb4f5cb5ae4b3d7d2da3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_filter/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bd4e0aaddf0a6c1884b87d7e667d6c6eb7c7e06efa5ab47422fc60a3b3efef71",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_epg/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_static_binding_to_epg",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_static_binding_to_epg/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e1b29a9a51fce0d2f865d00a3b952298abbb6f25b4fca3117de5b4994139a52e",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_static_binding_to_epg/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9d7ff43eec015a9f3f9572411178bf9b79312d587a38c1f7b145593873225d39",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki/admin_invalid.key",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "55fb85eae133a7b8649703b1d6e303cdf5b585d381e761f3674d1fcc5beb40cb",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8a74dffaf7d04e74642988302b185f0e9eda2dd35a5b7f32317696b12a9790c1",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f97928b2cd1ce43cfe9ae9bbf47a40b858a749c4c3f25a7ec02898611f4fee90",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki/openssh_rsa.key",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "81a6ac3a61f2df64339252db67fea1307e891c41232e2da53a1e5219f677c917",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki/admin.key",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "947c1b5a6c419641d4b2c8492b91f2d71588958666aeceeffb1f878460b1d256",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "77629e6b31c8c9fad7052f4696dcead786fecef66e33e81c50ce09fcb39d8b4a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6945fcb844179106a63be7e8ea5b407f31a8a1e95a1eaa0b5e67da1c26802032",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_ctx_profile",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_ctx_profile/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b975c93d5b5349200870eb59a8d67f48ac2125d0aa4e58e6538784d88d037769",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_ctx_profile/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e2efff70368092af76367a837d66ec0f5f213e8f2dcb18f86ff17387635367b7",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out_extepg",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out_extepg/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out_extepg/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c48c8e04da56cfc813a2d61eefe6f967f1fa960b7a47ee0249399561118e3a12",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l2out_extepg/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_static_routes",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_static_routes/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_static_routes/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fb2042728b7d89dfc37377cb2bb4220e18b6cf1559fa96fa249c86c02274e215",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_l3out_static_routes/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_zone",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_zone/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_zone/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1068d22db9147852b860870ac376782f1e7dde0a36b1a6864b644e99271a23ca",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_zone/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_leaf_selector",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_leaf_selector/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "92eff154bbd10cb5f9c4f29a6df3db4449b5b492bc1005aa6526b18d7d70cdbc",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_leaf_selector/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_region",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_region/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_region/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "81276c113cd83391e893462842a0700fc1a1bf27c9802acd596023e0cb406992",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_region/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_leaf_profile",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_leaf_profile/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "df9813a66a2f13fcb63dc567c9c837dd5361fd8cd95d11bf7acc0161fc74314b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_leaf_profile/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vmm_credential",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vmm_credential/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vmm_credential/tasks/vmware.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d5a44d6dc013507d32ffe42b42fdf6ddb5d0b7926fd36a7940083ed390db1a59",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vmm_credential/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3160edcdbd1b730523e2239ca29b9ce2050d22d65028504573171f59b2a62e82",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_vmm_credential/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3665afd2390c61d564b42ec3d5d198283a16c947a332e441c3d0cf6234e06b82",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_rollback",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_rollback/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_rollback/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "91881432f41395ee83f079d8c9eafa410c41deaa076b0606f33b9818dc6271f9",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_config_rollback/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_port_security",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_port_security/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5ff9173fc6507a1aca48cffa0748004a8055bfeae76e9f9479e6a8eb3f780a1f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_interface_policy_port_security/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_system",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_system/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_system/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "258a556f7e0b3951c846d808b4da3fc59645ea08e03895990ec9734777196fcc",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_system/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_dhcp_label",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_dhcp_label/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7a723f08c47ecd1f395e357fc117549dccf050580ba706b647aea98332ed8a4e",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_bd_dhcp_label/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool/tasks/vsan.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6d3a61c7dd273ea3d25fc294fd6cb6d389f6eeb92d7475827bfd2be86800d7b9",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool/tasks/vlan.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7eb94b25fdef72fa4505a685d0c269e030e4be19e7ef4b07d19d420d142a73f0",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool/tasks/vxlan.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ac938a576416da777b9fb855810f8dd1d582470b0a6b04c3da971be25a9ecfeb",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "78202505d750c4fd93a314def948be7e95516c4bb820cd9aed37ebd58b3c44ea",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_encap_pool/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks/json_inline.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a1ff9d6891ccf01fa4dcb08f1de31fe4e484d7d56632dce362989c6b5f731887",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks/json_string.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "27682e4605d65f1d9b188eddcb49aa7881cec73309ab5d519e5cf5b26379a13f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks/yaml_inline.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "56f653f63378ed596d11764df28f5703066d41d3b8829bc6efb91807a60f1c30",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks/xml_string.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7c1720f00012ec0e72d8bda66f6407bc24b724d04baf77d0404cfe1b89af21ab",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks/yaml_string.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "56f653f63378ed596d11764df28f5703066d41d3b8829bc6efb91807a60f1c30",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b28a5c321130fdea95a8fe4b349662f499fec0d1bd10fa4f190df9154d798fcc",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/tasks/error_handling.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5e118317b9f9438907e0e9c327afcfb4adc2feefdbd646b97df53890e9359553",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_rest/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject_to_filter",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject_to_filter/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4c4e96f5fd47e53addc3c926b16011820324542e82a7700ba756ee76e75610be",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_contract_subject_to_filter/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_sub_port_block_to_access_port",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9338f942c41c0dd7a2ef0165c41b1b36800e2dfc376f7822a49106b8d1f0a87f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_cidr",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_cidr/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_cidr/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "50047d8dbfeb8d2015ad34d4174710a4c283c0c63c88a8b80fefb2ad5f7daab9",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/aci_cloud_cidr/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "616f27a9a7bb49e561ef3782330e18d1a8cea3840e3166e798796684dd546a69",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/network-integration.requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "61902b3c85adc8a2143950820ed906014fbbc48b98f1dcdbc3ea3edf36c84f0a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/target-prefixes.network",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "febb2a0938d28c21b2834600aa14a4878723de041f5f95a9c753dc7fe14794f3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/inventory.networking",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "71c715d3172e5995476fcb005eb7367b04df579567d0ed9c31208de69cf82725",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c8a4ac4bfdef88e75d6e748e35a42fb4915947dfa2b7dd788626fd829600e014",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/ignore-2.10.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/ignore-2.9.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/.gitignore",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b5726d3ec9335a09c124469eca039523847a6b0f08a083efaefd002b83326600",
+ "format": 1
+ },
+ {
+ "name": "meta",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "meta/runtime.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "48a2f61c72296aaa190a3ad670b0a5759bd047262b59b3d870e986b05878d87d",
+ "format": 1
+ },
+ {
+ "name": "changelogs",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "changelogs/config.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3e20eced2de0cbf27b3220fcf0e10f59ef770591c430effa860ce0ceba6c0cbf",
+ "format": 1
+ },
+ {
+ "name": "changelogs/.gitignore",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "919ef00776e7d2ff349950ac4b806132aa9faf006e214d5285de54533e443b33",
+ "format": 1
+ },
+ {
+ "name": "changelogs/.plugin-cache.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8d4a9e6df40c7c8cc866cce31a6f009e8128ecdc478825e04efe176a09bd488b",
+ "format": 1
+ },
+ {
+ "name": "changelogs/changelog.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d54dc2777895e53a8d11e3f4959259db0cb12eb7a5d0407edc08503df4374611",
+ "format": 1
+ },
+ {
+ "name": "README.md",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9a92f358d773d20208cf3d33bc9b0c297ee9e097ecf04369b558c9fa0a3ae5b8",
+ "format": 1
+ },
+ {
+ "name": ".gitignore",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c407a0218d3e6adafc83a5c5ff8a5df0bd63aa887c414756810efe035ea67e33",
+ "format": 1
+ },
+ {
+ "name": ".github",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": ".github/workflows",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": ".github/workflows/ansible-test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e736c682ce3d31fa3698816eb359042baf3d6e1af46c063d32df17dedc23324d",
+ "format": 1
+ },
+ {
+ "name": "CHANGELOG.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4a13d21a307458494ced0f3b9a0545b08924361fe23ec09b7db7e7b38b0ecb69",
+ "format": 1
+ },
+ {
+ "name": ".vscode",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": ".vscode/settings.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d7f0d7666ed5a63b02508a1d58a523d82f97aeeae83659e2ad4bc33dc2e25070",
+ "format": 1
+ }
+ ],
+ "format": 1
+} \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/LICENSE b/collections-debian-merged/ansible_collections/cisco/aci/LICENSE
new file mode 100644
index 00000000..e09a4143
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/LICENSE
@@ -0,0 +1,678 @@
+Copyright (c) 2019, Cisco Systems
+All rights reserved.
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/MANIFEST.json b/collections-debian-merged/ansible_collections/cisco/aci/MANIFEST.json
new file mode 100644
index 00000000..594286d9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/MANIFEST.json
@@ -0,0 +1,45 @@
+{
+ "collection_info": {
+ "namespace": "cisco",
+ "name": "aci",
+ "version": "1.1.1",
+ "authors": [
+ "Dag Wieers (@dagwieers) <dag@wieers.com>",
+ "Swetha Chunduri (@schunduri)",
+ "Jacob McGill (@jmcgill298)",
+ "Rob Huelga (@RobW3LGA)",
+ "Bruno Calogero <brunocalogero@hotmail.com>",
+ "Simon Metzger <smnmtzgr@gmail.com>",
+ "Tim Knipper <tim.knipper@gmail.com>",
+ "Apoorva Gururaja (@aciguru)",
+ "Devarshi Shah (@devarshishah3)",
+ "Ramses Smeyers (@rsmeyers)",
+ "Lionel Hercot (@lhercot) <lhercot@cisco.com>"
+ ],
+ "readme": "README.md",
+ "tags": [
+ "cisco",
+ "aci",
+ "cloud",
+ "collection",
+ "networking",
+ "sdn"
+ ],
+ "description": "Ansible Modules for Cisco ACI",
+ "license": [],
+ "license_file": "LICENSE",
+ "dependencies": {},
+ "repository": "https://github.com/CiscoDevNet/ansible-aci",
+ "documentation": "https://docs.ansible.com/ansible/latest/scenario_guides/guide_aci.html",
+ "homepage": "https://github.com/CiscoDevNet/ansible-aci",
+ "issues": "https://github.com/CiscoDevNet/ansible-aci/issues"
+ },
+ "file_manifest_file": {
+ "name": "FILES.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8646ec2754f5caace3ddf61b0105408f918de0ee2664906215c5039c9f8d40d0",
+ "format": 1
+ },
+ "format": 1
+} \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/README.md b/collections-debian-merged/ansible_collections/cisco/aci/README.md
new file mode 100644
index 00000000..4e5cdf6a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/README.md
@@ -0,0 +1,91 @@
+# ansible-aci
+
+The ansible-aci project provides an Ansible collection for managing and automating your Cisco ACI environment. It consists of a set of modules and roles for performing tasks related to ACI.
+
+This collection has been tested and supports ACI 3.2+.
+Modules supporting new features introduced in ACI API in specific ACI versions might not be supported in earlier ACI releases.
+
+*Note: This collection is not compatible with versions of Ansible before v2.8.*
+
+## Requirements
+Ansible v2.9 or newer
+
+## Install
+Ansible must be installed
+```
+sudo pip install ansible
+```
+
+Install the collection
+```
+ansible-galaxy collection install cisco.aci
+```
+## Use
+Once the collection is installed, you can use it in a playbook by specifying the full namespace path to the module, plugin and/or role.
+
+```
+- hosts: aci
+ gather_facts: no
+
+ tasks:
+ - name: Add a new EPG
+ cisco.aci.aci_epg:
+ hostname: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ap: intranet
+ epg: web_epg
+ description: Web Intranet EPG
+ bd: prod_bd
+ delegate_to: localhost
+```
+
+## Update
+Getting the latest/nightly collection build
+
+### First Approach
+Clone the ansible-aci repository.
+```
+git clone https://github.com/CiscoDevNet/ansible-aci.git
+```
+
+Go to the ansible-aci directory
+```
+cd ansible-aci
+```
+
+Pull the latest master on your aci
+```
+git pull origin master
+```
+
+Build and Install a collection from source
+```
+ansible-galaxy collection build --force
+ansible-galaxy collection install cisco-aci-* --force
+```
+
+### Second Approach
+Go to: https://github.com/CiscoDevNet/ansible-aci/actions
+
+Select the latest CI build
+
+Under Artifacts download collection and unzip it using Terminal or Console.
+
+*Note: The collection file is a zip file containing a tar.gz file. We recommend using CLI because some GUI-based unarchiver might unarchive both nested archives in one go.*
+
+Install the unarchived tar.gz file
+```
+ansible-galaxy collection install cisco-aci-1.0.0.tar.gz —-force
+```
+
+### See Also:
+
+* [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
+
+## Contributing to this collection
+
+Ongoing development efforts and contributions to this collection are tracked as issues in this repository.
+
+We welcome community contributions to this collection. If you find problems, need an enhancement or need a new module, please open an issue or create a PR against the [Cisco ACI collection repository](https://github.com/CiscoDevNet/ansible-aci/issues).
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/changelogs/.gitignore b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/.gitignore
new file mode 100644
index 00000000..6be6b533
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/.gitignore
@@ -0,0 +1 @@
+/.plugin-cache.yaml
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml
new file mode 100644
index 00000000..eeebb8f7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/.plugin-cache.yaml
@@ -0,0 +1,444 @@
+plugins:
+ become: {}
+ cache: {}
+ callback: {}
+ cliconf: {}
+ connection: {}
+ httpapi: {}
+ inventory: {}
+ lookup: {}
+ module:
+ aci_aaa_user:
+ description: Manage AAA users (aaa:User)
+ name: aci_aaa_user
+ namespace: ''
+ version_added: null
+ aci_aaa_user_certificate:
+ description: Manage AAA user certificates (aaa:UserCert)
+ name: aci_aaa_user_certificate
+ namespace: ''
+ version_added: null
+ aci_access_port_block_to_access_port:
+ description: Manage port blocks of Fabric interface policy leaf profile interface
+ selectors (infra:HPortS, infra:PortBlk)
+ name: aci_access_port_block_to_access_port
+ namespace: ''
+ version_added: null
+ aci_access_port_to_interface_policy_leaf_profile:
+ description: Manage Fabric interface policy leaf profile interface selectors
+ (infra:HPortS, infra:RsAccBaseGrp, infra:PortBlk)
+ name: aci_access_port_to_interface_policy_leaf_profile
+ namespace: ''
+ version_added: null
+ aci_access_sub_port_block_to_access_port:
+ description: Manage sub port blocks of Fabric interface policy leaf profile
+ interface selectors (infra:HPortS, infra:SubPortBlk)
+ name: aci_access_sub_port_block_to_access_port
+ namespace: ''
+ version_added: null
+ aci_aep:
+ description: Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP,
+ infra:ProvAcc)
+ name: aci_aep
+ namespace: ''
+ version_added: null
+ aci_aep_to_domain:
+ description: Bind AEPs to Physical or Virtual Domains (infra:RsDomP)
+ name: aci_aep_to_domain
+ namespace: ''
+ version_added: null
+ aci_ap:
+ description: Manage top level Application Profile (AP) objects (fv:Ap)
+ name: aci_ap
+ namespace: ''
+ version_added: null
+ aci_bd:
+ description: Manage Bridge Domains (BD) objects (fv:BD)
+ name: aci_bd
+ namespace: ''
+ version_added: null
+ aci_bd_dhcp_label:
+ description: Manage DHCP Labels (dhcp:Lbl)
+ name: aci_bd_dhcp_label
+ namespace: ''
+ version_added: null
+ aci_bd_subnet:
+ description: Manage Subnets (fv:Subnet)
+ name: aci_bd_subnet
+ namespace: ''
+ version_added: null
+ aci_bd_to_l3out:
+ description: Bind Bridge Domain to L3 Out (fv:RsBDToOut)
+ name: aci_bd_to_l3out
+ namespace: ''
+ version_added: null
+ aci_cloud_cidr:
+ description: Manage CIDR under Cloud Context Profile (cloud:Cidr)
+ name: aci_cloud_cidr
+ namespace: ''
+ version_added: null
+ aci_cloud_ctx_profile:
+ description: Manage Cloud Context Profile (cloud:CtxProfile)
+ name: aci_cloud_ctx_profile
+ namespace: ''
+ version_added: null
+ aci_cloud_provider:
+ description: Query Cloud Provider information (cloud:ProvP)
+ name: aci_cloud_provider
+ namespace: ''
+ version_added: null
+ aci_cloud_region:
+ description: Manage Cloud Providers Region (cloud:Region)
+ name: aci_cloud_region
+ namespace: ''
+ version_added: null
+ aci_cloud_subnet:
+ description: Manage Cloud Subnet (cloud:Subnet)
+ name: aci_cloud_subnet
+ namespace: ''
+ version_added: null
+ aci_cloud_vpn_gateway:
+ description: Manage cloudRouterP in Cloud Context Profile (cloud:cloudRouterP)
+ name: aci_cloud_vpn_gateway
+ namespace: ''
+ version_added: null
+ aci_cloud_zone:
+ description: Manage Cloud Availability Zone (cloud:Zone)
+ name: aci_cloud_zone
+ namespace: ''
+ version_added: null
+ aci_config_rollback:
+ description: Provides rollback and rollback preview functionality (config:ImportP)
+ name: aci_config_rollback
+ namespace: ''
+ version_added: null
+ aci_config_snapshot:
+ description: Manage Config Snapshots (config:Snapshot, config:ExportP)
+ name: aci_config_snapshot
+ namespace: ''
+ version_added: null
+ aci_contract:
+ description: Manage contract resources (vz:BrCP)
+ name: aci_contract
+ namespace: ''
+ version_added: null
+ aci_contract_subject:
+ description: Manage initial Contract Subjects (vz:Subj)
+ name: aci_contract_subject
+ namespace: ''
+ version_added: null
+ aci_contract_subject_to_filter:
+ description: Bind Contract Subjects to Filters (vz:RsSubjFiltAtt)
+ name: aci_contract_subject_to_filter
+ namespace: ''
+ version_added: null
+ aci_domain:
+ description: Manage physical, virtual, bridged, routed or FC domain profiles
+ (phys:DomP, vmm:DomP, l2ext:DomP, l3ext:DomP, fc:DomP)
+ name: aci_domain
+ namespace: ''
+ version_added: null
+ aci_domain_to_encap_pool:
+ description: Bind Domain to Encap Pools (infra:RsVlanNs)
+ name: aci_domain_to_encap_pool
+ namespace: ''
+ version_added: null
+ aci_domain_to_vlan_pool:
+ description: Bind Domain to VLAN Pools (infra:RsVlanNs)
+ name: aci_domain_to_vlan_pool
+ namespace: ''
+ version_added: null
+ aci_encap_pool:
+ description: Manage encap pools (fvns:VlanInstP, fvns:VxlanInstP, fvns:VsanInstP)
+ name: aci_encap_pool
+ namespace: ''
+ version_added: null
+ aci_encap_pool_range:
+ description: Manage encap ranges assigned to pools (fvns:EncapBlk, fvns:VsanEncapBlk)
+ name: aci_encap_pool_range
+ namespace: ''
+ version_added: null
+ aci_epg:
+ description: Manage End Point Groups (EPG) objects (fv:AEPg)
+ name: aci_epg
+ namespace: ''
+ version_added: null
+ aci_epg_monitoring_policy:
+ description: Manage monitoring policies (mon:EPGPol)
+ name: aci_epg_monitoring_policy
+ namespace: ''
+ version_added: null
+ aci_epg_to_contract:
+ description: Bind EPGs to Contracts (fv:RsCons, fv:RsProv)
+ name: aci_epg_to_contract
+ namespace: ''
+ version_added: null
+ aci_epg_to_contract_master:
+ description: Manage End Point Group (EPG) contract master relationships (fv:RsSecInherited)
+ name: aci_epg_to_contract_master
+ namespace: ''
+ version_added: null
+ aci_epg_to_domain:
+ description: Bind EPGs to Domains (fv:RsDomAtt)
+ name: aci_epg_to_domain
+ namespace: ''
+ version_added: null
+ aci_fabric_node:
+ description: Manage Fabric Node Members (fabric:NodeIdentP)
+ name: aci_fabric_node
+ namespace: ''
+ version_added: null
+ aci_fabric_scheduler:
+ description: This modules creates ACI schedulers.
+ name: aci_fabric_scheduler
+ namespace: ''
+ version_added: null
+ aci_filter:
+ description: Manages top level filter objects (vz:Filter)
+ name: aci_filter
+ namespace: ''
+ version_added: null
+ aci_filter_entry:
+ description: Manage filter entries (vz:Entry)
+ name: aci_filter_entry
+ namespace: ''
+ version_added: null
+ aci_firmware_group:
+ description: This module creates a firmware group
+ name: aci_firmware_group
+ namespace: ''
+ version_added: null
+ aci_firmware_group_node:
+ description: This modules adds and remove nodes from the firmware group
+ name: aci_firmware_group_node
+ namespace: ''
+ version_added: null
+ aci_firmware_policy:
+ description: This creates a firmware policy
+ name: aci_firmware_policy
+ namespace: ''
+ version_added: null
+ aci_firmware_source:
+ description: Manage firmware image sources (firmware:OSource)
+ name: aci_firmware_source
+ namespace: ''
+ version_added: null
+ aci_interface_policy_cdp:
+ description: Manage CDP interface policies (cdp:IfPol)
+ name: aci_interface_policy_cdp
+ namespace: ''
+ version_added: null
+ aci_interface_policy_fc:
+ description: Manage Fibre Channel interface policies (fc:IfPol)
+ name: aci_interface_policy_fc
+ namespace: ''
+ version_added: null
+ aci_interface_policy_l2:
+ description: Manage Layer 2 interface policies (l2:IfPol)
+ name: aci_interface_policy_l2
+ namespace: ''
+ version_added: null
+ aci_interface_policy_leaf_breakout_port_group:
+ description: Manage fabric interface policy leaf breakout port group (infra:BrkoutPortGrp)
+ name: aci_interface_policy_leaf_breakout_port_group
+ namespace: ''
+ version_added: null
+ aci_interface_policy_leaf_policy_group:
+ description: Manage fabric interface policy leaf policy groups (infra:AccBndlGrp,
+ infra:AccPortGrp)
+ name: aci_interface_policy_leaf_policy_group
+ namespace: ''
+ version_added: null
+ aci_interface_policy_leaf_profile:
+ description: Manage fabric interface policy leaf profiles (infra:AccPortP)
+ name: aci_interface_policy_leaf_profile
+ namespace: ''
+ version_added: null
+ aci_interface_policy_link_level:
+ description: Manage Link Level interface policies (fabric:HIfPol)
+ name: aci_interface_policy_link_level
+ namespace: ''
+ version_added: null
+ aci_interface_policy_lldp:
+ description: Manage LLDP interface policies (lldp:IfPol)
+ name: aci_interface_policy_lldp
+ namespace: ''
+ version_added: null
+ aci_interface_policy_mcp:
+ description: Manage MCP interface policies (mcp:IfPol)
+ name: aci_interface_policy_mcp
+ namespace: ''
+ version_added: null
+ aci_interface_policy_ospf:
+ description: Manage OSPF interface policies (ospf:IfPol)
+ name: aci_interface_policy_ospf
+ namespace: ''
+ version_added: null
+ aci_interface_policy_port_channel:
+ description: Manage port channel interface policies (lacp:LagPol)
+ name: aci_interface_policy_port_channel
+ namespace: ''
+ version_added: null
+ aci_interface_policy_port_security:
+ description: Manage port security (l2:PortSecurityPol)
+ name: aci_interface_policy_port_security
+ namespace: ''
+ version_added: null
+ aci_interface_selector_to_switch_policy_leaf_profile:
+ description: Bind interface selector profiles to switch policy leaf profiles
+ (infra:RsAccPortP)
+ name: aci_interface_selector_to_switch_policy_leaf_profile
+ namespace: ''
+ version_added: null
+ aci_l2out:
+ description: Manage Layer2 Out (L2Out) objects.
+ name: aci_l2out
+ namespace: ''
+ version_added: null
+ aci_l2out_extepg:
+ description: Manage External Network Instance (L2Out External EPG) objects (l2extInstP).
+ name: aci_l2out_extepg
+ namespace: ''
+ version_added: null
+ aci_l3out:
+ description: Manage Layer 3 Outside (L3Out) objects (l3ext:Out)
+ name: aci_l3out
+ namespace: ''
+ version_added: null
+ aci_l3out_extepg:
+ description: Manage External Network Instance Profile (ExtEpg) objects (l3extInstP:instP)
+ name: aci_l3out_extepg
+ namespace: ''
+ version_added: null
+ aci_l3out_extepg_to_contract:
+ description: Bind Contracts to External End Point Groups (EPGs)
+ name: aci_l3out_extepg_to_contract
+ namespace: ''
+ version_added: null
+ aci_l3out_extsubnet:
+ description: Manage External Subnet objects (l3extSubnet:extsubnet)
+ name: aci_l3out_extsubnet
+ namespace: ''
+ version_added: null
+ aci_l3out_logical_interface_vpc_member:
+ description: Manage Member Node objects (l3extMember:Member)
+ name: aci_l3out_logical_interface_vpc_member
+ namespace: ''
+ version_added: null
+ aci_l3out_route_tag_policy:
+ description: Manage route tag policies (l3ext:RouteTagPol)
+ name: aci_l3out_route_tag_policy
+ namespace: ''
+ version_added: null
+ aci_l3out_static_routes:
+ description: Manage Static routes object (l3ext:ipRouteP)
+ name: aci_l3out_static_routes
+ namespace: ''
+ version_added: null
+ aci_maintenance_group:
+ description: This creates an ACI maintenance group
+ name: aci_maintenance_group
+ namespace: ''
+ version_added: null
+ aci_maintenance_group_node:
+ description: Manage maintenance group nodes
+ name: aci_maintenance_group_node
+ namespace: ''
+ version_added: null
+ aci_maintenance_policy:
+ description: Manage firmware maintenance policies
+ name: aci_maintenance_policy
+ namespace: ''
+ version_added: null
+ aci_rest:
+ description: Direct access to the Cisco APIC REST API
+ name: aci_rest
+ namespace: ''
+ version_added: null
+ aci_static_binding_to_epg:
+ description: Bind static paths to EPGs (fv:RsPathAtt)
+ name: aci_static_binding_to_epg
+ namespace: ''
+ version_added: null
+ aci_switch_leaf_selector:
+ description: Bind leaf selectors to switch policy leaf profiles (infra:LeafS,
+ infra:NodeBlk, infra:RsAccNodePGrep)
+ name: aci_switch_leaf_selector
+ namespace: ''
+ version_added: null
+ aci_switch_policy_leaf_profile:
+ description: Manage switch policy leaf profiles (infra:NodeP)
+ name: aci_switch_policy_leaf_profile
+ namespace: ''
+ version_added: null
+ aci_switch_policy_vpc_protection_group:
+ description: Manage switch policy explicit vPC protection groups (fabric:ExplicitGEp,
+ fabric:NodePEp).
+ name: aci_switch_policy_vpc_protection_group
+ namespace: ''
+ version_added: null
+ aci_system:
+ description: Query the ACI system information (top:System)
+ name: aci_system
+ namespace: ''
+ version_added: null
+ aci_taboo_contract:
+ description: Manage taboo contracts (vz:BrCP)
+ name: aci_taboo_contract
+ namespace: ''
+ version_added: null
+ aci_tenant:
+ description: Manage tenants (fv:Tenant)
+ name: aci_tenant
+ namespace: ''
+ version_added: null
+ aci_tenant_action_rule_profile:
+ description: Manage action rule profiles (rtctrl:AttrP)
+ name: aci_tenant_action_rule_profile
+ namespace: ''
+ version_added: null
+ aci_tenant_ep_retention_policy:
+ description: Manage End Point (EP) retention protocol policies (fv:EpRetPol)
+ name: aci_tenant_ep_retention_policy
+ namespace: ''
+ version_added: null
+ aci_tenant_span_dst_group:
+ description: Manage SPAN destination groups (span:DestGrp)
+ name: aci_tenant_span_dst_group
+ namespace: ''
+ version_added: null
+ aci_tenant_span_src_group:
+ description: Manage SPAN source groups (span:SrcGrp)
+ name: aci_tenant_span_src_group
+ namespace: ''
+ version_added: null
+ aci_tenant_span_src_group_to_dst_group:
+ description: Bind SPAN source groups to destination groups (span:SpanLbl)
+ name: aci_tenant_span_src_group_to_dst_group
+ namespace: ''
+ version_added: null
+ aci_vlan_pool:
+ description: Manage VLAN pools (fvns:VlanInstP)
+ name: aci_vlan_pool
+ namespace: ''
+ version_added: null
+ aci_vlan_pool_encap_block:
+ description: Manage encap blocks assigned to VLAN pools (fvns:EncapBlk)
+ name: aci_vlan_pool_encap_block
+ namespace: ''
+ version_added: null
+ aci_vmm_credential:
+ description: Manage virtual domain credential profiles (vmm:UsrAccP)
+ name: aci_vmm_credential
+ namespace: ''
+ version_added: null
+ aci_vrf:
+ description: Manage contexts or VRFs (fv:Ctx)
+ name: aci_vrf
+ namespace: ''
+ version_added: null
+ netconf: {}
+ shell: {}
+ strategy: {}
+ vars: {}
+version: 1.1.1
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/changelogs/changelog.yaml b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/changelog.yaml
new file mode 100644
index 00000000..a2163676
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/changelog.yaml
@@ -0,0 +1,102 @@
+ancestor: null
+releases:
+ 1.0.0:
+ changes:
+ bugfixes:
+ - Fix sanity issues to support 2.10.0
+ - Fix some doc issues for a few modules
+ - Fix some formatting issues (flake8) in unit tests.
+ - Fixing integration tests and sanity. Tested on ACI 4.2(3l).
+ minor_changes:
+ - Add Fex capability to aci_interface_policy_leaf_profile, aci_access_port_to_interface_policy_leaf_profile
+ and aci_access_port_block_to_access_port
+ - Add LICENSE file
+ - Add aci_epg_to_contract_master module
+ - Add annotation attribute to aci.py and to doc fragment.
+ - Add annotation to every payload and add test case for annotation.
+ - Add changelog
+ - Add collection prefix to all integration tests
+ - Add galaxy.yml file for collection listing
+ - Add github action CI pipeline
+ - Add module and test file for aci_bd_dhcp_label
+ - Add modules and test files for aci_cloud_ctx_profile, aci_cloud_cidr, aci_cloud_subnet
+ and aci_cloud_zone
+ - Add modules and test files for aci_l2out, aci_l2out_extepg and aci_l3out_extepg_to_contract
+ - Add names to documentation examples for modules from community.network
+ - Add preferred group support to aci_vrf
+ - Add support for Azure on all cloud modules
+ - Add support for output_path to allow dump of REST API objects
+ - Add support for owner_key and owner_tag for all modules and add test case
+ for it.
+ - Add vpn gateway dedicated module and remove vpn_gateway from cloud_ctx_profile
+ module
+ - Fix M() and module to use FQCN
+ - Initial commit based on the collection migration available at "ansible-collection-migration/cisco.aci"
+ which contains the ACI module from Ansible Core
+ - Move aci.py to base of module_utils and fix references
+ - Move test file to root of tests/unit/module_utils
+ - Update Ansible version in CI and add 2.10.0 to sanity in CI.
+ - Update Readme with supported versions
+ - Update to test files to make the tests work on both 3.2 and 4.2.
+ release_summary: 'This is the first official release of the ``cisco.aci`` collection
+ on 2020-08-18.
+
+ This changelog describes all changes made to the modules and plugins included
+ in this collection since Ansible 2.9.0.
+
+ '
+ release_date: '2020-08-18'
+ 1.0.1:
+ changes:
+ bugfixes:
+ - Fix convertion of json/yaml payload to xml in aci_rest
+ - Fix dump of config for aci_rest
+ - Fix issue of "current" in firmware_source module
+ - Fix sanity issue in aci_rest and bump version to v1.0.1
+ minor_changes:
+ - Enable/Disable infra vlan in aci_aep and its test module
+ - Set scope default value in aci_l3out_extsubnet
+ release_summary: 'Release v1.0.1 of the ``cisco.mso`` collection on 2020-10-13.
+
+ This changelog describes all changes made to the modules and plugins included
+ in this collection since v1.0.0. '
+ release_date: '2020-10-13'
+ 1.1.0:
+ changes:
+ bugfixes:
+ - Existing_config variable is not reset during loop
+ - Fix galaxy import warnings
+ - Fix how validity of private key/private key file is checked to support new
+ types
+ - Fix incorrect domain types in aci_domain_to_encap_pool module
+ minor_changes:
+ - Ability to add monitoring policy to epgs and anps
+ - Add Ansible Network ENV to fallback
+ - Add aci_l3out_external_path_to_member.py & aci_l3out_static_routes modules
+ - Add env_fallback for common connection params
+ - Add env_fallback for the rest of the argument spec
+ - Add new Subclass path support
+ - Add new module and test file for leaf breakout port group
+ - Added failure message to aci_interface_policy_leaf_policy_group
+ - Update README.md
+ - Update inventory
+ - aci_epg_to_domain addition of promiscuous mode (#79)
+ - aci_interface_policy_port_security addition of attribute:timeout (#80)
+ release_summary: 'Release v1.1.0 of the ``cisco.mso`` collection on 2020-10-30.
+
+ This changelog describes all changes made to the modules and plugins included
+ in this collection since v1.0.1. '
+ release_date: '2020-10-30'
+ 1.1.1:
+ changes:
+ bugfixes:
+ - Fix galaxy import warnings
+ - Fix sanity issue in aci_epg_to_domain
+ minor_changes:
+ - Add test file for aci_domain_to_encap_pool
+ - aci_epg_to_domain moving child configs & classes to each domain type
+ release_summary: 'Release v1.1.1 of the ``cisco.mso`` collection on 2020-11-23.
+
+ This changelog describes all changes made to the modules and plugins included
+ in this collection since v1.1.0. '
+ release_date: '2020-11-23'
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/changelogs/config.yaml b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/config.yaml
new file mode 100644
index 00000000..1d6198ea
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/changelogs/config.yaml
@@ -0,0 +1,31 @@
+changelog_filename_template: ../CHANGELOG.rst
+changelog_filename_version_depth: 0
+changes_file: changelog.yaml
+changes_format: combined
+ignore_other_fragment_extensions: true
+keep_fragments: false
+mention_ancestor: true
+new_plugins_after_name: removed_features
+notesdir: fragments
+prelude_section_name: release_summary
+prelude_section_title: Release Summary
+sections:
+- - major_changes
+ - Major Changes
+- - minor_changes
+ - Minor Changes
+- - breaking_changes
+ - Breaking Changes / Porting Guide
+- - deprecated_features
+ - Deprecated Features
+- - removed_features
+ - Removed Features (previously deprecated)
+- - security_fixes
+ - Security Fixes
+- - bugfixes
+ - Bugfixes
+- - known_issues
+ - Known Issues
+title: Cisco ACI Ansible Collection
+trivial_section_name: trivial
+use_fqcn: true
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/meta/runtime.yml b/collections-debian-merged/ansible_collections/cisco/aci/meta/runtime.yml
new file mode 100644
index 00000000..1f18fd72
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/meta/runtime.yml
@@ -0,0 +1,2 @@
+---
+requires_ansible: '>=2.9.10' \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py
new file mode 100644
index 00000000..38266656
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/doc_fragments/aci.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
+# Copyright: (c) 2017, Swetha Chunduri (@schunduri)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+class ModuleDocFragment(object):
+ # Standard files documentation fragment
+ DOCUMENTATION = r'''
+options:
+ host:
+ description:
+ - IP Address or hostname of APIC resolvable by Ansible control host.
+ - If the value is not specified in the task, the value of environment variable C(ACI_HOST) will be used instead.
+ type: str
+ required: yes
+ aliases: [ hostname ]
+ port:
+ description:
+ - Port number to be used for REST connection.
+ - The default value depends on parameter C(use_ssl).
+ - If the value is not specified in the task, the value of environment variable C(ACI_PORT) will be used instead.
+ type: int
+ username:
+ description:
+ - The username to use for authentication.
+ - If the value is not specified in the task, the value of environment variables C(ACI_USERNAME) or C(ANSIBLE_NET_USERNAME) will be used instead.
+ type: str
+ default: admin
+ aliases: [ user ]
+ password:
+ description:
+ - The password to use for authentication.
+ - This option is mutual exclusive with C(private_key). If C(private_key) is provided too, it will be used instead.
+ - If the value is not specified in the task, the value of environment variables C(ACI_PASSWORD) or C(ANSIBLE_NET_PASSWORD) will be used instead.
+ type: str
+ private_key:
+ description:
+ - Either a PEM-formatted private key file or the private key content used for signature-based authentication.
+ - This value also influences the default C(certificate_name) that is used.
+ - This option is mutual exclusive with C(password). If C(password) is provided too, it will be ignored.
+ - If the value is not specified in the task, the value of environment variable C(ACI_PRIVATE_KEY) will be used instead.
+ type: str
+ aliases: [ cert_key ]
+ certificate_name:
+ description:
+ - The X.509 certificate name attached to the APIC AAA user used for signature-based authentication.
+ - If a C(private_key) filename was provided, this defaults to the C(private_key) basename, without extension.
+ - If PEM-formatted content was provided for C(private_key), this defaults to the C(username) value.
+ - If the value is not specified in the task, the value of environment variable C(ACI_CERTIFICATE_NAME) will be used instead.
+ type: str
+ aliases: [ cert_name ]
+ output_level:
+ description:
+ - Influence the output of this ACI module.
+ - C(normal) means the standard output, incl. C(current) dict
+ - C(info) adds informational output, incl. C(previous), C(proposed) and C(sent) dicts
+ - C(debug) adds debugging output, incl. C(filter_string), C(method), C(response), C(status) and C(url) information
+ - If the value is not specified in the task, the value of environment variable C(ACI_OUTPUT_LEVEL) will be used instead.
+ type: str
+ choices: [ debug, info, normal ]
+ default: normal
+ timeout:
+ description:
+ - The socket level timeout in seconds.
+ - If the value is not specified in the task, the value of environment variable C(ACI_TIMEOUT) will be used instead.
+ type: int
+ default: 30
+ use_proxy:
+ description:
+ - If C(no), it will not use a proxy, even if one is defined in an environment variable on the target hosts.
+ - If the value is not specified in the task, the value of environment variable C(ACI_USE_PROXY) will be used instead.
+ type: bool
+ default: yes
+ use_ssl:
+ description:
+ - If C(no), an HTTP connection will be used instead of the default HTTPS connection.
+ - If the value is not specified in the task, the value of environment variable C(ACI_USE_SSL) will be used instead.
+ type: bool
+ default: yes
+ validate_certs:
+ description:
+ - If C(no), SSL certificates will not be validated.
+ - This should only set to C(no) when used on personally controlled sites using self-signed certificates.
+ - If the value is not specified in the task, the value of environment variable C(ACI_VALIDATE_CERTS) will be used instead.
+ type: bool
+ default: yes
+ output_path:
+ description:
+ - Path to a file that will be used to dump the ACI JSON configuration objects generated by the module.
+ - If the value is not specified in the task, the value of environment variable C(ACI_OUTPUT_PATH) will be used instead.
+ type: str
+ annotation:
+ description:
+ - User-defined string for annotating an object.
+ - If the value is not specified in the task, the value of environment variable C(ACI_ANNOTATION) will be used instead.
+ type: str
+ owner_key:
+ description:
+ - User-defined string for the ownerKey attribute of an ACI object.
+ - This attribute represents a key for enabling clients to own their data for entity correlation.
+ - If the value is not specified in the task, the value of environment variable C(ACI_OWNER_KEY) will be used instead.
+ type: str
+ owner_tag:
+ description:
+ - User-defined string for the ownerTag attribute of an ACI object.
+ - This attribute represents a tag for enabling clients to add their own data.
+ - For example, to indicate who created this object.
+ - If the value is not specified in the task, the value of environment variable C(ACI_OWNER_TAG) will be used instead.
+ type: str
+seealso:
+- ref: aci_guide
+ description: Detailed information on how to manage your ACI infrastructure using Ansible.
+- ref: aci_dev_guide
+ description: Detailed guide on how to write your own Cisco ACI modules to contribute.
+'''
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/aci.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/aci.py
new file mode 100644
index 00000000..9e0759f1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/module_utils/aci.py
@@ -0,0 +1,1336 @@
+# -*- coding: utf-8 -*-
+
+# This code is part of Ansible, but is an independent component
+
+# This particular file snippet, and this file snippet only, is BSD licensed.
+# Modules you write using this snippet, which is embedded dynamically by Ansible
+# still belong to the author of the module, and may assign their own license
+# to the complete work.
+
+# Copyright: (c) 2017, Dag Wieers <dag@wieers.com>
+# Copyright: (c) 2017, Jacob McGill (@jmcgill298)
+# Copyright: (c) 2017, Swetha Chunduri (@schunduri)
+# Copyright: (c) 2019, Rob Huelga (@RobW3LGA)
+# Copyright: (c) 2020, Lionel Hercot (@lhercot) <lhercot@cisco.com>
+# All rights reserved.
+
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import base64
+import json
+import os
+from copy import deepcopy
+
+from ansible.module_utils.urls import fetch_url
+from ansible.module_utils._text import to_bytes, to_native
+from ansible.module_utils.basic import env_fallback
+
+# Optional, only used for APIC signature-based authentication
+try:
+ from OpenSSL.crypto import FILETYPE_PEM, load_privatekey, sign
+ HAS_OPENSSL = True
+except ImportError:
+ HAS_OPENSSL = False
+
+# Optional, only used for XML payload
+try:
+ import lxml.etree
+ HAS_LXML_ETREE = True
+except ImportError:
+ HAS_LXML_ETREE = False
+
+# Optional, only used for XML payload
+try:
+ from xmljson import cobra
+ HAS_XMLJSON_COBRA = True
+except ImportError:
+ HAS_XMLJSON_COBRA = False
+
+
+def aci_argument_spec():
+ return dict(
+ host=dict(type='str', required=True, aliases=['hostname'], fallback=(env_fallback, ['ACI_HOST'])),
+ port=dict(type='int', required=False, fallback=(env_fallback, ['ACI_PORT'])),
+ username=dict(type='str', default='admin', aliases=['user'], fallback=(env_fallback, ['ACI_USERNAME', 'ANSIBLE_NET_USERNAME'])),
+ password=dict(type='str', no_log=True, fallback=(env_fallback, ['ACI_PASSWORD', 'ANSIBLE_NET_PASSWORD'])),
+ # Beware, this is not the same as client_key !
+ private_key=dict(type='str', aliases=['cert_key'], no_log=True, fallback=(env_fallback, ['ACI_PRIVATE_KEY'])),
+ # Beware, this is not the same as client_cert !
+ certificate_name=dict(type='str', aliases=['cert_name'], fallback=(env_fallback, ['ACI_CERTIFICATE_NAME'])),
+ output_level=dict(type='str', default='normal', choices=['debug', 'info', 'normal'], fallback=(env_fallback, ['ACI_OUTPUT_LEVEL'])),
+ timeout=dict(type='int', default=30, fallback=(env_fallback, ['ACI_TIMEOUT'])),
+ use_proxy=dict(type='bool', default=True, fallback=(env_fallback, ['ACI_USE_PROXY'])),
+ use_ssl=dict(type='bool', default=True, fallback=(env_fallback, ['ACI_USE_SSL'])),
+ validate_certs=dict(type='bool', default=True, fallback=(env_fallback, ['ACI_VALIDATE_CERTS'])),
+ output_path=dict(type='str', fallback=(env_fallback, ['ACI_OUTPUT_PATH'])),
+ annotation=dict(type='str', fallback=(env_fallback, ['ACI_ANNOTATION'])),
+ owner_key=dict(type='str', fallback=(env_fallback, ['ACI_OWNER_KEY'])),
+ owner_tag=dict(type='str', fallback=(env_fallback, ['ACI_OWNER_TAG'])),
+ )
+
+
+class ACIModule(object):
+
+ def __init__(self, module):
+ self.module = module
+ self.params = module.params
+ self.result = dict(changed=False)
+ self.headers = dict()
+ self.child_classes = set()
+
+ # error output
+ self.error = dict(code=None, text=None)
+
+ # normal output
+ self.existing = None
+
+ # info output
+ self.config = dict()
+ self.original = None
+ self.proposed = dict()
+ self.stdout = None
+
+ # debug output
+ self.filter_string = ''
+ self.obj_filter = None
+ self.method = None
+ self.path = None
+ self.response = None
+ self.status = None
+ self.url = None
+
+ # aci_rest output
+ self.imdata = None
+ self.totalCount = None
+
+ # Ensure protocol is set
+ self.define_protocol()
+
+ if self.module._debug:
+ self.module.warn('Enable debug output because ANSIBLE_DEBUG was set.')
+ self.params['output_level'] = 'debug'
+
+ if self.params.get('private_key'):
+ # Perform signature-based authentication, no need to log on separately
+ if not HAS_OPENSSL:
+ self.module.fail_json(msg='Cannot use signature-based authentication because pyopenssl is not available')
+ elif self.params.get('password') is not None:
+ self.module.warn("When doing ACI signatured-based authentication, providing parameter 'password' is not required")
+ elif self.params.get('password'):
+ # Perform password-based authentication, log on using password
+ self.login()
+ else:
+ self.module.fail_json(msg="Either parameter 'password' or 'private_key' is required for authentication")
+
+ def boolean(self, value, true='yes', false='no'):
+ ''' Return an acceptable value back '''
+
+ # When we expect value is of type=bool
+ if value is None:
+ return None
+ elif value is True:
+ return true
+ elif value is False:
+ return false
+
+ # If all else fails, escalate back to user
+ self.module.fail_json(msg="Boolean value '%s' is an invalid ACI boolean value.")
+
+ def iso8601_format(self, dt):
+ ''' Return an ACI-compatible ISO8601 formatted time: 2123-12-12T00:00:00.000+00:00 '''
+ try:
+ return dt.isoformat(timespec='milliseconds')
+ except Exception:
+ tz = dt.strftime('%z')
+ return '%s.%03d%s:%s' % (dt.strftime('%Y-%m-%dT%H:%M:%S'), dt.microsecond / 1000, tz[:3], tz[3:])
+
+ def define_protocol(self):
+ ''' Set protocol based on use_ssl parameter '''
+
+ # Set protocol for further use
+ self.params['protocol'] = 'https' if self.params.get('use_ssl', True) else 'http'
+
+ def define_method(self):
+ ''' Set method based on state parameter '''
+
+ # Set method for further use
+ state_map = dict(absent='delete', present='post', query='get')
+ self.params['method'] = state_map.get(self.params.get('state'))
+
+ def login(self):
+ ''' Log in to APIC '''
+
+ # Perform login request
+ if self.params.get('port') is not None:
+ url = '%(protocol)s://%(host)s:%(port)s/api/aaaLogin.json' % self.params
+ else:
+ url = '%(protocol)s://%(host)s/api/aaaLogin.json' % self.params
+ payload = {'aaaUser': {'attributes': {'name': self.params.get('username'), 'pwd': self.params.get('password')}}}
+ resp, auth = fetch_url(self.module, url,
+ data=json.dumps(payload),
+ method='POST',
+ timeout=self.params.get('timeout'),
+ use_proxy=self.params.get('use_proxy'))
+
+ # Handle APIC response
+ if auth.get('status') != 200:
+ self.response = auth.get('msg')
+ self.status = auth.get('status')
+ try:
+ # APIC error
+ self.response_json(auth['body'])
+ self.fail_json(msg='Authentication failed: %(code)s %(text)s' % self.error)
+ except KeyError:
+ # Connection error
+ self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % auth)
+
+ # Retain cookie for later use
+ self.headers['Cookie'] = resp.headers.get('Set-Cookie')
+
+ def cert_auth(self, path=None, payload='', method=None):
+ ''' Perform APIC signature-based authentication, not the expected SSL client certificate authentication. '''
+
+ if method is None:
+ method = self.params.get('method').upper()
+
+ # NOTE: ACI documentation incorrectly uses complete URL
+ if path is None:
+ path = self.path
+ path = '/' + path.lstrip('/')
+
+ if payload is None:
+ payload = ''
+
+ # Check if we got a private key. This allows the use of vaulting the private key.
+ try:
+ sig_key = load_privatekey(FILETYPE_PEM, self.params.get('private_key'))
+ except Exception:
+ if os.path.exists(self.params.get('private_key')):
+ try:
+ with open(self.params.get('private_key'), 'r') as fh:
+ private_key_content = fh.read()
+ except Exception:
+ self.module.fail_json(msg="Cannot open private key file '%(private_key)s'." % self.params)
+ try:
+ sig_key = load_privatekey(FILETYPE_PEM, private_key_content)
+ except Exception:
+ self.module.fail_json(msg="Cannot load private key file '%(private_key)s'." % self.params)
+ if self.params.get('certificate_name') is None:
+ self.params['certificate_name'] = os.path.basename(os.path.splitext(self.params.get('private_key'))[0])
+ else:
+ self.module.fail_json(msg="Provided private key '%(private_key)s' does not appear to be a private key." % self.params)
+
+ if self.params.get('certificate_name') is None:
+ self.params['certificate_name'] = self.params.get('username')
+ # NOTE: ACI documentation incorrectly adds a space between method and path
+ sig_request = method + path + payload
+ sig_signature = base64.b64encode(sign(sig_key, sig_request, 'sha256'))
+ sig_dn = 'uni/userext/user-%(username)s/usercert-%(certificate_name)s' % self.params
+ self.headers['Cookie'] = 'APIC-Certificate-Algorithm=v1.0; ' +\
+ 'APIC-Certificate-DN=%s; ' % sig_dn +\
+ 'APIC-Certificate-Fingerprint=fingerprint; ' +\
+ 'APIC-Request-Signature=%s' % to_native(sig_signature)
+
+ def response_json(self, rawoutput):
+ ''' Handle APIC JSON response output '''
+ try:
+ jsondata = json.loads(rawoutput)
+ except Exception as e:
+ # Expose RAW output for troubleshooting
+ self.error = dict(code=-1, text="Unable to parse output as JSON, see 'raw' output. %s" % e)
+ self.result['raw'] = rawoutput
+ return
+
+ # Extract JSON API output
+ self.imdata = jsondata.get('imdata')
+ if self.imdata is None:
+ self.imdata = dict()
+ self.totalCount = int(jsondata.get('totalCount'))
+
+ # Handle possible APIC error information
+ self.response_error()
+
+ def response_xml(self, rawoutput):
+ ''' Handle APIC XML response output '''
+
+ # NOTE: The XML-to-JSON conversion is using the "Cobra" convention
+ try:
+ xml = lxml.etree.fromstring(to_bytes(rawoutput))
+ xmldata = cobra.data(xml)
+ except Exception as e:
+ # Expose RAW output for troubleshooting
+ self.error = dict(code=-1, text="Unable to parse output as XML, see 'raw' output. %s" % e)
+ self.result['raw'] = rawoutput
+ return
+
+ # Reformat as ACI does for JSON API output
+ self.imdata = xmldata.get('imdata', {}).get('children')
+ if self.imdata is None:
+ self.imdata = dict()
+ self.totalCount = int(xmldata.get('imdata', {}).get('attributes', {}).get('totalCount'))
+
+ # Handle possible APIC error information
+ self.response_error()
+
+ def response_error(self):
+ ''' Set error information when found '''
+
+ # Handle possible APIC error information
+ if self.totalCount != '0':
+ try:
+ self.error = self.imdata[0].get('error').get('attributes')
+ except (AttributeError, IndexError, KeyError):
+ pass
+
+ def request(self, path, payload=None):
+ ''' Perform a REST request '''
+
+ # Ensure method is set (only do this once)
+ self.define_method()
+ self.path = path
+
+ if self.params.get('port') is not None:
+ self.url = '%(protocol)s://%(host)s:%(port)s/' % self.params + path.lstrip('/')
+ else:
+ self.url = '%(protocol)s://%(host)s/' % self.params + path.lstrip('/')
+
+ # Sign and encode request as to APIC's wishes
+ if self.params.get('private_key'):
+ self.cert_auth(path=path, payload=payload)
+
+ # Perform request
+ resp, info = fetch_url(self.module, self.url,
+ data=payload,
+ headers=self.headers,
+ method=self.params.get('method').upper(),
+ timeout=self.params.get('timeout'),
+ use_proxy=self.params.get('use_proxy'))
+
+ self.response = info.get('msg')
+ self.status = info.get('status')
+
+ # Handle APIC response
+ if info.get('status') != 200:
+ try:
+ # APIC error
+ self.response_json(info['body'])
+ self.fail_json(msg='APIC Error %(code)s: %(text)s' % self.error)
+ except KeyError:
+ # Connection error
+ self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
+
+ self.response_json(resp.read())
+
+ def query(self, path):
+ ''' Perform a query with no payload '''
+
+ self.path = path
+
+ if self.params.get('port') is not None:
+ self.url = '%(protocol)s://%(host)s:%(port)s/' % self.params + path.lstrip('/')
+ else:
+ self.url = '%(protocol)s://%(host)s/' % self.params + path.lstrip('/')
+
+ # Sign and encode request as to APIC's wishes
+ if self.params.get('private_key'):
+ self.cert_auth(path=path, method='GET')
+
+ # Perform request
+ resp, query = fetch_url(self.module, self.url,
+ data=None,
+ headers=self.headers,
+ method='GET',
+ timeout=self.params.get('timeout'),
+ use_proxy=self.params.get('use_proxy'))
+
+ # Handle APIC response
+ if query.get('status') != 200:
+ self.response = query.get('msg')
+ self.status = query.get('status')
+ try:
+ # APIC error
+ self.response_json(query['body'])
+ self.fail_json(msg='APIC Error %(code)s: %(text)s' % self.error)
+ except KeyError:
+ # Connection error
+ self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % query)
+
+ query = json.loads(resp.read())
+
+ return json.dumps(query.get('imdata'), sort_keys=True, indent=2) + '\n'
+
+ def request_diff(self, path, payload=None):
+ ''' Perform a request, including a proper diff output '''
+ self.result['diff'] = dict()
+ self.result['diff']['before'] = self.query(path)
+ self.request(path, payload=payload)
+ # TODO: Check if we can use the request output for the 'after' diff
+ self.result['diff']['after'] = self.query(path)
+
+ if self.result.get('diff', {}).get('before') != self.result.get('diff', {}).get('after'):
+ self.result['changed'] = True
+
+ # TODO: This could be designed to update existing keys
+ def update_qs(self, params):
+ ''' Append key-value pairs to self.filter_string '''
+ accepted_params = dict((k, v) for (k, v) in params.items() if v is not None)
+ if accepted_params:
+ if self.filter_string:
+ self.filter_string += '&'
+ else:
+ self.filter_string = '?'
+ self.filter_string += '&'.join(['%s=%s' % (k, v) for (k, v) in accepted_params.items()])
+
+ # TODO: This could be designed to accept multiple obj_classes and keys
+ def build_filter(self, obj_class, params):
+ ''' Build an APIC filter based on obj_class and key-value pairs '''
+ accepted_params = dict((k, v) for (k, v) in params.items() if v is not None)
+ if len(accepted_params) == 1:
+ return ','.join('eq({0}.{1},"{2}")'.format(obj_class, k, v) for (k, v) in accepted_params.items())
+ elif len(accepted_params) > 1:
+ return 'and(' + ','.join(['eq({0}.{1},"{2}")'.format(obj_class, k, v) for (k, v) in accepted_params.items()]) + ')'
+
+ def _deep_url_path_builder(self, obj):
+ target_class = obj.get('target_class')
+ target_filter = obj.get('target_filter')
+ subtree_class = obj.get('subtree_class')
+ subtree_filter = obj.get('subtree_filter')
+ object_rn = obj.get('object_rn')
+ mo = obj.get('module_object')
+ add_subtree_filter = obj.get('add_subtree_filter')
+ add_target_filter = obj.get('add_target_filter')
+
+ if self.module.params.get('state') in ('absent', 'present') and mo is not None:
+ self.path = 'api/mo/uni/{0}.json'.format(object_rn)
+ self.update_qs({'rsp-prop-include': 'config-only'})
+
+ else:
+ # State is 'query'
+ if object_rn is not None:
+ # Query for a specific object in the module's class
+ self.path = 'api/mo/uni/{0}.json'.format(object_rn)
+ else:
+ self.path = 'api/class/{0}.json'.format(target_class)
+
+ if add_target_filter:
+ self.update_qs(
+ {'query-target-filter': self.build_filter(target_class, target_filter)})
+
+ if add_subtree_filter:
+ self.update_qs(
+ {'rsp-subtree-filter': self.build_filter(subtree_class, subtree_filter)})
+
+ if self.params.get('port') is not None:
+ self.url = '{protocol}://{host}:{port}/{path}'.format(
+ path=self.path, **self.module.params)
+
+ else:
+ self.url = '{protocol}://{host}/{path}'.format(
+ path=self.path, **self.module.params)
+
+ if self.child_classes:
+ self.update_qs(
+ {'rsp-subtree': 'full', 'rsp-subtree-class': ','.join(sorted(self.child_classes))})
+
+ def _deep_url_parent_object(self, parent_objects, parent_class):
+
+ for parent_object in parent_objects:
+ if parent_object.get('aci_class') is parent_class:
+ return parent_object
+
+ return None
+
+ def construct_deep_url(self, target_object, parent_objects=None, child_classes=None):
+ """
+ This method is used to retrieve the appropriate URL path and filter_string to make the request to the APIC.
+
+ :param target_object: The target class dictionary containing parent_class, aci_class, aci_rn, target_filter, and module_object keys.
+ :param parent_objects: The parent class list of dictionaries containing parent_class, aci_class, aci_rn, target_filter, and module_object keys.
+ :param child_classes: The list of child classes that the module supports along with the object.
+ :type target_object: dict
+ :type parent_objects: list[dict]
+ :type child_classes: list[string]
+ :return: The path and filter_string needed to build the full URL.
+ """
+
+ self.filter_string = ''
+ rn_builder = None
+ subtree_classes = None
+ add_subtree_filter = False
+ add_target_filter = False
+ has_target_query = False
+ has_target_query_compare = False
+ has_target_query_difference = False
+ has_target_query_called = False
+
+ if child_classes is None:
+ self.child_classes = set()
+ else:
+ self.child_classes = set(child_classes)
+
+ target_parent_class = target_object.get('parent_class')
+ target_class = target_object.get('aci_class')
+ target_rn = target_object.get('aci_rn')
+ target_filter = target_object.get('target_filter')
+ target_module_object = target_object.get('module_object')
+
+ url_path_object = dict(
+ target_class=target_class,
+ target_filter=target_filter,
+ subtree_class=target_class,
+ subtree_filter=target_filter,
+ module_object=target_module_object
+ )
+
+ if target_module_object is not None:
+ rn_builder = target_rn
+ else:
+ has_target_query = True
+ has_target_query_compare = True
+
+ if parent_objects is not None:
+ current_parent_class = target_parent_class
+ has_parent_query_compare = False
+ has_parent_query_difference = False
+ is_first_parent = True
+ is_single_parent = None
+ search_classes = set()
+
+ while current_parent_class != 'uni':
+ parent_object = self._deep_url_parent_object(
+ parent_objects=parent_objects, parent_class=current_parent_class)
+
+ if parent_object is not None:
+ parent_parent_class = parent_object.get('parent_class')
+ parent_class = parent_object.get('aci_class')
+ parent_rn = parent_object.get('aci_rn')
+ parent_filter = parent_object.get('target_filter')
+ parent_module_object = parent_object.get('module_object')
+
+ if is_first_parent:
+ is_single_parent = True
+ else:
+ is_single_parent = False
+ is_first_parent = False
+
+ if parent_parent_class != 'uni':
+ search_classes.add(parent_class)
+
+ if parent_module_object is not None:
+ if rn_builder is not None:
+ rn_builder = '{0}/{1}'.format(parent_rn, rn_builder)
+ else:
+ rn_builder = parent_rn
+
+ url_path_object['target_class'] = parent_class
+ url_path_object['target_filter'] = parent_filter
+
+ has_target_query = False
+ else:
+ rn_builder = None
+ subtree_classes = search_classes
+
+ has_target_query = True
+ if is_single_parent:
+ has_parent_query_compare = True
+
+ current_parent_class = parent_parent_class
+ else:
+ raise ValueError("Reference error for parent_class '{0}'. Each parent_class must reference a valid object".format(current_parent_class))
+
+ if not has_target_query_difference and not has_target_query_called:
+ if has_target_query is not has_target_query_compare:
+ has_target_query_difference = True
+ else:
+ if not has_parent_query_difference and has_target_query is not has_parent_query_compare:
+ has_parent_query_difference = True
+ has_target_query_called = True
+
+ if not has_parent_query_difference and has_parent_query_compare and target_module_object is not None:
+ add_target_filter = True
+
+ elif has_parent_query_difference and target_module_object is not None:
+ add_subtree_filter = True
+ self.child_classes.add(target_class)
+
+ if has_target_query:
+ add_target_filter = True
+
+ elif has_parent_query_difference and not has_target_query and target_module_object is None:
+ self.child_classes.add(target_class)
+ self.child_classes.update(subtree_classes)
+
+ elif not has_parent_query_difference and not has_target_query and target_module_object is None:
+ self.child_classes.add(target_class)
+
+ elif not has_target_query and is_single_parent and target_module_object is None:
+ self.child_classes.add(target_class)
+
+ url_path_object['object_rn'] = rn_builder
+ url_path_object['add_subtree_filter'] = add_subtree_filter
+ url_path_object['add_target_filter'] = add_target_filter
+
+ self._deep_url_path_builder(url_path_object)
+
+ def construct_url(
+ self, root_class, subclass_1=None, subclass_2=None, subclass_3=None,
+ subclass_4=None, subclass_5=None, child_classes=None, config_only=True):
+
+ """
+ This method is used to retrieve the appropriate URL path and filter_string to make the request to the APIC.
+
+ :param root_class: The top-level class dictionary containing aci_class, aci_rn, target_filter, and module_object keys.
+ :param sublass_1: The second-level class dictionary containing aci_class, aci_rn, target_filter, and module_object keys.
+ :param sublass_2: The third-level class dictionary containing aci_class, aci_rn, target_filter, and module_object keys.
+ :param sublass_3: The fourth-level class dictionary containing aci_class, aci_rn, target_filter, and module_object keys.
+ :param child_classes: The list of child classes that the module supports along with the object.
+ :type root_class: dict
+ :type subclass_1: dict
+ :type subclass_2: dict
+ :type subclass_3: dict
+ :type subclass_4: dict
+ :type subclass_5: dict
+ :type child_classes: list
+ :return: The path and filter_string needed to build the full URL.
+ """
+ self.filter_string = ''
+
+ if child_classes is None:
+ self.child_classes = set()
+ else:
+ self.child_classes = set(child_classes)
+
+ if subclass_5 is not None:
+ self._construct_url_6(root_class, subclass_1, subclass_2, subclass_3, subclass_4, subclass_5, config_only)
+ elif subclass_4 is not None:
+ self._construct_url_5(root_class, subclass_1, subclass_2, subclass_3, subclass_4, config_only)
+ elif subclass_3 is not None:
+ self._construct_url_4(root_class, subclass_1, subclass_2, subclass_3, config_only)
+ elif subclass_2 is not None:
+ self._construct_url_3(root_class, subclass_1, subclass_2, config_only)
+ elif subclass_1 is not None:
+ self._construct_url_2(root_class, subclass_1, config_only)
+ else:
+ self._construct_url_1(root_class, config_only)
+
+ if self.params.get('port') is not None:
+ self.url = '{protocol}://{host}:{port}/{path}'.format(path=self.path, **self.module.params)
+ else:
+ self.url = '{protocol}://{host}/{path}'.format(path=self.path, **self.module.params)
+
+ if self.child_classes:
+ # Append child_classes to filter_string if filter string is empty
+ self.update_qs({'rsp-subtree': 'full', 'rsp-subtree-class': ','.join(sorted(self.child_classes))})
+
+ def _construct_url_1(self, obj, config_only=True):
+ """
+ This method is used by construct_url when the object is the top-level class.
+ """
+ obj_class = obj.get('aci_class')
+ obj_rn = obj.get('aci_rn')
+ obj_filter = obj.get('target_filter')
+ mo = obj.get('module_object')
+
+ if self.module.params.get('state') in ('absent', 'present'):
+ # State is absent or present
+ self.path = 'api/mo/uni/{0}.json'.format(obj_rn)
+ if config_only:
+ self.update_qs({'rsp-prop-include': 'config-only'})
+ self.obj_filter = obj_filter
+ elif mo is None:
+ # Query for all objects of the module's class (filter by properties)
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ if obj_filter is not None:
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ else:
+ # Query for a specific object in the module's class
+ self.path = 'api/mo/uni/{0}.json'.format(obj_rn)
+
+ def _construct_url_2(self, parent, obj, config_only=True):
+ """
+ This method is used by construct_url when the object is the second-level class.
+ """
+ parent_rn = parent.get('aci_rn')
+ parent_obj = parent.get('module_object')
+ obj_class = obj.get('aci_class')
+ obj_rn = obj.get('aci_rn')
+ obj_filter = obj.get('target_filter')
+ mo = obj.get('module_object')
+
+ if self.module.params.get('state') in ('absent', 'present'):
+ # State is absent or present
+ self.path = 'api/mo/uni/{0}/{1}.json'.format(parent_rn, obj_rn)
+ if config_only:
+ self.update_qs({'rsp-prop-include': 'config-only'})
+ self.obj_filter = obj_filter
+ elif parent_obj is None and mo is None:
+ # Query for all objects of the module's class
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ elif parent_obj is None: # mo is known
+ # Query for all objects of the module's class that match the provided ID value
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ elif mo is None: # parent_obj is known
+ # Query for all object's of the module's class that belong to a specific parent object
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}.json'.format(parent_rn)
+ else:
+ # Query for specific object in the module's class
+ self.path = 'api/mo/uni/{0}/{1}.json'.format(parent_rn, obj_rn)
+
+ def _construct_url_3(self, root, parent, obj, config_only=True):
+ """
+ This method is used by construct_url when the object is the third-level class.
+ """
+ root_rn = root.get('aci_rn')
+ root_obj = root.get('module_object')
+ parent_class = parent.get('aci_class')
+ parent_rn = parent.get('aci_rn')
+ parent_filter = parent.get('target_filter')
+ parent_obj = parent.get('module_object')
+ obj_class = obj.get('aci_class')
+ obj_rn = obj.get('aci_rn')
+ obj_filter = obj.get('target_filter')
+ mo = obj.get('module_object')
+
+ if self.module.params.get('state') in ('absent', 'present'):
+ # State is absent or present
+ self.path = 'api/mo/uni/{0}/{1}/{2}.json'.format(root_rn, parent_rn, obj_rn)
+ if config_only:
+ self.update_qs({'rsp-prop-include': 'config-only'})
+ self.obj_filter = obj_filter
+ elif root_obj is None and parent_obj is None and mo is None:
+ # Query for all objects of the module's class
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ elif root_obj is None and parent_obj is None: # mo is known
+ # Query for all objects of the module's class matching the provided ID value of the object
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ elif root_obj is None and mo is None: # parent_obj is known
+ # Query for all objects of the module's class that belong to any parent class
+ # matching the provided ID value for the parent object
+ self.child_classes.add(obj_class)
+ self.path = 'api/class/{0}.json'.format(parent_class)
+ self.update_qs({'query-target-filter': self.build_filter(parent_class, parent_filter)})
+ elif parent_obj is None and mo is None: # root_obj is known
+ # Query for all objects of the module's class that belong to a specific root object
+ self.child_classes.update([parent_class, obj_class])
+ self.path = 'api/mo/uni/{0}.json'.format(root_rn)
+ # NOTE: No need to select by root_filter
+ # self.update_qs({'query-target-filter': self.build_filter(root_class, root_filter)})
+ elif root_obj is None: # mo and parent_obj are known
+ # Query for all objects of the module's class that belong to any parent class
+ # matching the provided ID values for both object and parent object
+ self.child_classes.add(obj_class)
+ self.path = 'api/class/{0}.json'.format(parent_class)
+ self.update_qs({'query-target-filter': self.build_filter(parent_class, parent_filter)})
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif parent_obj is None: # mo and root_obj are known
+ # Query for all objects of the module's class that match the provided ID value and belong to a specific root object
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}.json'.format(root_rn)
+ # NOTE: No need to select by root_filter
+ # self.update_qs({'query-target-filter': self.build_filter(root_class, root_filter)})
+ # TODO: Filter by parent_filter and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif mo is None: # root_obj and parent_obj are known
+ # Query for all objects of the module's class that belong to a specific parent object
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}/{1}.json'.format(root_rn, parent_rn)
+ # NOTE: No need to select by parent_filter
+ # self.update_qs({'query-target-filter': self.build_filter(parent_class, parent_filter)})
+ else:
+ # Query for a specific object of the module's class
+ self.path = 'api/mo/uni/{0}/{1}/{2}.json'.format(root_rn, parent_rn, obj_rn)
+
+ def _construct_url_4(self, root, sec, parent, obj, config_only=True):
+ """
+ This method is used by construct_url when the object is the fourth-level class.
+ """
+ root_rn = root.get('aci_rn')
+ root_obj = root.get('module_object')
+ sec_rn = sec.get('aci_rn')
+ sec_obj = sec.get('module_object')
+ parent_rn = parent.get('aci_rn')
+ parent_obj = parent.get('module_object')
+ obj_class = obj.get('aci_class')
+ obj_rn = obj.get('aci_rn')
+ obj_filter = obj.get('target_filter')
+ mo = obj.get('module_object')
+
+ if self.child_classes is None:
+ self.child_classes = [obj_class]
+
+ if self.module.params.get('state') in ('absent', 'present'):
+ # State is absent or present
+ self.path = 'api/mo/uni/{0}/{1}/{2}/{3}.json'.format(root_rn, sec_rn, parent_rn, obj_rn)
+ if config_only:
+ self.update_qs({'rsp-prop-include': 'config-only'})
+ self.obj_filter = obj_filter
+ # TODO: Add all missing cases
+ elif root_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ elif sec_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}.json'.format(root_rn)
+ # NOTE: No need to select by root_filter
+ # self.update_qs({'query-target-filter': self.build_filter(root_class, root_filter)})
+ # TODO: Filter by sec_filter, parent and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif parent_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}/{1}.json'.format(root_rn, sec_rn)
+ # NOTE: No need to select by sec_filter
+ # self.update_qs({'query-target-filter': self.build_filter(sec_class, sec_filter)})
+ # TODO: Filter by parent_filter and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif mo is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}/{1}/{2}.json'.format(root_rn, sec_rn, parent_rn)
+ # NOTE: No need to select by parent_filter
+ # self.update_qs({'query-target-filter': self.build_filter(parent_class, parent_filter)})
+ else:
+ # Query for a specific object of the module's class
+ self.path = 'api/mo/uni/{0}/{1}/{2}/{3}.json'.format(root_rn, sec_rn, parent_rn, obj_rn)
+
+ def _construct_url_5(self, root, ter, sec, parent, obj, config_only=True):
+ """
+ This method is used by construct_url when the object is the fourth-level class.
+ """
+
+ root_rn = root.get('aci_rn')
+ root_obj = root.get('module_object')
+ ter_rn = ter.get('aci_rn')
+ ter_obj = ter.get('module_object')
+ sec_rn = sec.get('aci_rn')
+ sec_obj = sec.get('module_object')
+ parent_rn = parent.get('aci_rn')
+ parent_obj = parent.get('module_object')
+ obj_class = obj.get('aci_class')
+ obj_rn = obj.get('aci_rn')
+ obj_filter = obj.get('target_filter')
+ mo = obj.get('module_object')
+
+ if self.child_classes is None:
+ self.child_classes = [obj_class]
+
+ if self.module.params.get('state') in ('absent', 'present'):
+ # State is absent or present
+ self.path = 'api/mo/uni/{0}/{1}/{2}/{3}{4}.json'.format(root_rn, ter_rn, sec_rn, parent_rn, obj_rn)
+ if config_only:
+ self.update_qs({'rsp-prop-include': 'config-only'})
+ self.obj_filter = obj_filter
+ # TODO: Add all missing cases
+ elif root_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ elif ter_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}.json'.format(root_rn)
+ # NOTE: No need to select by root_filter
+ # self.update_qs({'query-target-filter': self.build_filter(root_class, root_filter)})
+ # TODO: Filter by ter_filter, parent and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif sec_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}{1}.json'.format(root_rn, ter_rn)
+ # NOTE: No need to select by ter_filter
+ # self.update_qs({'query-target-filter': self.build_filter(ter_class, ter_filter)})
+ # TODO: Filter by sec_filter, parent and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif parent_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}/{1}{2}.json'.format(root_rn, ter_rn, sec_rn)
+ # NOTE: No need to select by sec_filter
+ # self.update_qs({'query-target-filter': self.build_filter(sec_class, sec_filter)})
+ # TODO: Filter by parent_filter and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif mo is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}/{1}/{2}{3}.json'.format(root_rn, ter_rn, sec_rn, parent_rn)
+ # NOTE: No need to select by parent_filter
+ # self.update_qs({'query-target-filter': self.build_filter(parent_class, parent_filter)})
+ else:
+ # Query for a specific object of the module's class
+ self.path = 'api/mo/uni/{0}/{1}/{2}/{3}{4}.json'.format(root_rn, ter_rn, sec_rn, parent_rn, obj_rn)
+
+ def _construct_url_6(self, root, quad, ter, sec, parent, obj, config_only=True):
+ """
+ This method is used by construct_url when the object is the fourth-level class.
+ """
+ root_rn = root.get('aci_rn')
+ root_obj = root.get('module_object')
+ quad_rn = quad.get('aci_rn')
+ quad_obj = quad.get('module_object')
+ ter_rn = ter.get('aci_rn')
+ ter_obj = ter.get('module_object')
+ sec_rn = sec.get('aci_rn')
+ sec_obj = sec.get('module_object')
+ parent_rn = parent.get('aci_rn')
+ parent_obj = parent.get('module_object')
+ obj_class = obj.get('aci_class')
+ obj_rn = obj.get('aci_rn')
+ obj_filter = obj.get('target_filter')
+ mo = obj.get('module_object')
+
+ if self.child_classes is None:
+ self.child_classes = [obj_class]
+
+ if self.module.params.get('state') in ('absent', 'present'):
+ # State is absent or present
+ self.path = 'api/mo/uni/{0}/{1}/{2}/{3}{4}{5}.json'.format(root_rn, quad_rn, ter_rn, sec_rn, parent_rn, obj_rn)
+ if config_only:
+ self.update_qs({'rsp-prop-include': 'config-only'})
+ self.obj_filter = obj_filter
+ # TODO: Add all missing cases
+ elif root_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/class/{0}.json'.format(obj_class)
+ self.update_qs({'query-target-filter': self.build_filter(obj_class, obj_filter)})
+ elif quad_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}.json'.format(root_rn)
+ # NOTE: No need to select by root_filter
+ # self.update_qs({'query-target-filter': self.build_filter(root_class, root_filter)})
+ # TODO: Filter by quad_filter, parent and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif ter_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}{1}.json'.format(root_rn, quad_rn)
+ # NOTE: No need to select by quad_filter
+ # self.update_qs({'query-target-filter': self.build_filter(quad_class, quad_filter)})
+ # TODO: Filter by ter_filter, parent and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif sec_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}{1}{2}.json'.format(root_rn, quad_rn, ter_rn)
+ # NOTE: No need to select by ter_filter
+ # self.update_qs({'query-target-filter': self.build_filter(ter_class, ter_filter)})
+ # TODO: Filter by sec_filter, parent and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif parent_obj is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}/{1}{2}{3}.json'.format(root_rn, quad_rn, ter_rn, sec_rn)
+ # NOTE: No need to select by sec_filter
+ # self.update_qs({'query-target-filter': self.build_filter(sec_class, sec_filter)})
+ # TODO: Filter by parent_filter and obj_filter
+ self.update_qs({'rsp-subtree-filter': self.build_filter(obj_class, obj_filter)})
+ elif mo is None:
+ self.child_classes.add(obj_class)
+ self.path = 'api/mo/uni/{0}/{1}/{2}{3}{4}.json'.format(root_rn, quad_rn, ter_rn, sec_rn, parent_rn)
+ # NOTE: No need to select by parent_filter
+ # self.update_qs({'query-target-filter': self.build_filter(parent_class, parent_filter)})
+ else:
+ # Query for a specific object of the module's class
+ self.path = 'api/mo/uni/{0}/{1}/{2}/{3}{4}{5}.json'.format(root_rn, quad_rn, ter_rn, sec_rn, parent_rn, obj_rn)
+
+ def delete_config(self):
+ """
+ This method is used to handle the logic when the modules state is equal to absent. The method only pushes a change if
+ the object exists, and if check_mode is False. A successful change will mark the module as changed.
+ """
+ self.proposed = dict()
+
+ if not self.existing:
+ return
+
+ elif not self.module.check_mode:
+ # Sign and encode request as to APIC's wishes
+ if self.params['private_key']:
+ self.cert_auth(method='DELETE')
+
+ resp, info = fetch_url(self.module, self.url,
+ headers=self.headers,
+ method='DELETE',
+ timeout=self.params.get('timeout'),
+ use_proxy=self.params.get('use_proxy'))
+
+ self.response = info.get('msg')
+ self.status = info.get('status')
+ self.method = 'DELETE'
+
+ # Handle APIC response
+ if info.get('status') == 200:
+ self.result['changed'] = True
+ self.response_json(resp.read())
+ else:
+ try:
+ # APIC error
+ self.response_json(info['body'])
+ self.fail_json(msg='APIC Error %(code)s: %(text)s' % self.error)
+ except KeyError:
+ # Connection error
+ self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
+ else:
+ self.result['changed'] = True
+ self.method = 'DELETE'
+
+ def get_diff(self, aci_class):
+ """
+ This method is used to get the difference between the proposed and existing configurations. Each module
+ should call the get_existing method before this method, and add the proposed config to the module results
+ using the module's config parameters. The new config will added to the self.result dictionary.
+
+ :param aci_class: Type str.
+ This is the root dictionary key for the MO's configuration body, or the ACI class of the MO.
+ """
+ proposed_config = self.proposed[aci_class]['attributes']
+ if self.existing:
+ existing_config = self.existing[0][aci_class]['attributes']
+ config = {}
+
+ # values are strings, so any diff between proposed and existing can be a straight replace
+ for key, value in proposed_config.items():
+ existing_field = existing_config.get(key)
+ if value != existing_field:
+ config[key] = value
+
+ # add name back to config only if the configs do not match
+ if config:
+ # TODO: If URLs are built with the object's name, then we should be able to leave off adding the name back
+ # config['name'] = proposed_config.get('name')
+ config = {aci_class: {'attributes': config}}
+
+ # check for updates to child configs and update new config dictionary
+ children = self.get_diff_children(aci_class)
+ if children and config:
+ config[aci_class].update({'children': children})
+ elif children:
+ config = {aci_class: {'attributes': {}, 'children': children}}
+
+ else:
+ config = self.proposed
+
+ self.config = config
+
+ @staticmethod
+ def get_diff_child(child_class, proposed_child, existing_child):
+ """
+ This method is used to get the difference between a proposed and existing child configs. The get_nested_config()
+ method should be used to return the proposed and existing config portions of child.
+
+ :param child_class: Type str.
+ The root class (dict key) for the child dictionary.
+ :param proposed_child: Type dict.
+ The config portion of the proposed child dictionary.
+ :param existing_child: Type dict.
+ The config portion of the existing child dictionary.
+ :return: The child config with only values that are updated. If the proposed dictionary has no updates to make
+ to what exists on the APIC, then None is returned.
+ """
+ update_config = {child_class: {'attributes': {}}}
+ for key, value in proposed_child.items():
+ existing_field = existing_child.get(key)
+ if value != existing_field:
+ update_config[child_class]['attributes'][key] = value
+
+ if not update_config[child_class]['attributes']:
+ return None
+
+ return update_config
+
+ def get_diff_children(self, aci_class):
+ """
+ This method is used to retrieve the updated child configs by comparing the proposed children configs
+ agains the objects existing children configs.
+
+ :param aci_class: Type str.
+ This is the root dictionary key for the MO's configuration body, or the ACI class of the MO.
+ :return: The list of updated child config dictionaries. None is returned if there are no changes to the child
+ configurations.
+ """
+ proposed_children = self.proposed[aci_class].get('children')
+ if proposed_children:
+ child_updates = []
+ existing_children = self.existing[0][aci_class].get('children', [])
+
+ # Loop through proposed child configs and compare against existing child configuration
+ for child in proposed_children:
+ child_class, proposed_child, existing_child = self.get_nested_config(child, existing_children)
+
+ if existing_child is None:
+ child_update = child
+ else:
+ child_update = self.get_diff_child(child_class, proposed_child, existing_child)
+
+ # Update list of updated child configs only if the child config is different than what exists
+ if child_update:
+ child_updates.append(child_update)
+ else:
+ return None
+
+ return child_updates
+
+ def get_existing(self):
+ """
+ This method is used to get the existing object(s) based on the path specified in the module. Each module should
+ build the URL so that if the object's name is supplied, then it will retrieve the configuration for that particular
+ object, but if no name is supplied, then it will retrieve all MOs for the class. Following this method will ensure
+ that this method can be used to supply the existing configuration when using the get_diff method. The response, status,
+ and existing configuration will be added to the self.result dictionary.
+ """
+ uri = self.url + self.filter_string
+
+ # Sign and encode request as to APIC's wishes
+ if self.params.get('private_key'):
+ self.cert_auth(path=self.path + self.filter_string, method='GET')
+
+ resp, info = fetch_url(self.module, uri,
+ headers=self.headers,
+ method='GET',
+ timeout=self.params.get('timeout'),
+ use_proxy=self.params.get('use_proxy'))
+ self.response = info.get('msg')
+ self.status = info.get('status')
+ self.method = 'GET'
+
+ # Handle APIC response
+ if info.get('status') == 200:
+ self.existing = json.loads(resp.read())['imdata']
+ else:
+ try:
+ # APIC error
+ self.response_json(info['body'])
+ self.fail_json(msg='APIC Error %(code)s: %(text)s' % self.error)
+ except KeyError:
+ # Connection error
+ self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
+
+ @staticmethod
+ def get_nested_config(proposed_child, existing_children):
+ """
+ This method is used for stiping off the outer layers of the child dictionaries so only the configuration
+ key, value pairs are returned.
+
+ :param proposed_child: Type dict.
+ The dictionary that represents the child config.
+ :param existing_children: Type list.
+ The list of existing child config dictionaries.
+ :return: The child's class as str (root config dict key), the child's proposed config dict, and the child's
+ existing configuration dict.
+ """
+ for key in proposed_child.keys():
+ child_class = key
+ proposed_config = proposed_child[key]['attributes']
+ existing_config = None
+
+ # FIXME: Design causes issues for repeated child_classes
+ # get existing dictionary from the list of existing to use for comparison
+ for child in existing_children:
+ if child.get(child_class):
+ existing_config = child[key]['attributes']
+ # NOTE: This is an ugly fix
+ # Return the one that is a subset match
+ if set(proposed_config.items()).issubset(set(existing_config.items())):
+ break
+ existing_config = None
+
+ return child_class, proposed_config, existing_config
+
+ def payload(self, aci_class, class_config, child_configs=None):
+ """
+ This method is used to dynamically build the proposed configuration dictionary from the config related parameters
+ passed into the module. All values that were not passed values from the playbook task will be removed so as to not
+ inadvertently change configurations.
+
+ :param aci_class: Type str
+ This is the root dictionary key for the MO's configuration body, or the ACI class of the MO.
+ :param class_config: Type dict
+ This is the configuration of the MO using the dictionary keys expected by the API
+ :param child_configs: Type list
+ This is a list of child dictionaries associated with the MOs config. The list should only
+ include child objects that are used to associate two MOs together. Children that represent
+ MOs should have their own module.
+ """
+ proposed = dict((k, str(v)) for k, v in class_config.items() if v is not None)
+ if self.params.get('annotation') is not None:
+ proposed['annotation'] = self.params.get('annotation')
+ if self.params.get('owner_key') is not None:
+ proposed['ownerKey'] = self.params.get('owner_key')
+ if self.params.get('owner_tag') is not None:
+ proposed['ownerTag'] = self.params.get('owner_tag')
+ self.proposed = {aci_class: {'attributes': proposed}}
+
+ # add child objects to proposed
+ if child_configs:
+ children = []
+ for child in child_configs:
+ child_copy = deepcopy(child)
+ has_value = False
+ for root_key in child_copy.keys():
+ for final_keys, values in child_copy[root_key]['attributes'].items():
+ if values is None:
+ child[root_key]['attributes'].pop(final_keys)
+ else:
+ child[root_key]['attributes'][final_keys] = str(values)
+ has_value = True
+ if has_value:
+ children.append(child)
+
+ if children:
+ self.proposed[aci_class].update(dict(children=children))
+
+ def post_config(self):
+ """
+ This method is used to handle the logic when the modules state is equal to present. The method only pushes a change if
+ the object has differences than what exists on the APIC, and if check_mode is False. A successful change will mark the
+ module as changed.
+ """
+ if not self.config:
+ return
+ elif not self.module.check_mode:
+ # Sign and encode request as to APIC's wishes
+ if self.params.get('private_key'):
+ self.cert_auth(method='POST', payload=json.dumps(self.config))
+
+ resp, info = fetch_url(self.module, self.url,
+ data=json.dumps(self.config),
+ headers=self.headers,
+ method='POST',
+ timeout=self.params.get('timeout'),
+ use_proxy=self.params.get('use_proxy'))
+
+ self.response = info.get('msg')
+ self.status = info.get('status')
+ self.method = 'POST'
+
+ # Handle APIC response
+ if info.get('status') == 200:
+ self.result['changed'] = True
+ self.response_json(resp.read())
+ else:
+ try:
+ # APIC error
+ self.response_json(info['body'])
+ self.fail_json(msg='APIC Error %(code)s: %(text)s' % self.error)
+ except KeyError:
+ # Connection error
+ self.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
+ else:
+ self.result['changed'] = True
+ self.method = 'POST'
+
+ def exit_json(self, **kwargs):
+
+ if 'state' in self.params:
+ if self.params.get('state') in ('absent', 'present'):
+ if self.params.get('output_level') in ('debug', 'info'):
+ self.result['previous'] = self.existing
+ self.dump_json()
+
+ # Return the gory details when we need it
+ if self.params.get('output_level') == 'debug':
+ if 'state' in self.params:
+ self.result['filter_string'] = self.filter_string
+ self.result['method'] = self.method
+ # self.result['path'] = self.path # Adding 'path' in result causes state: absent in output
+ self.result['response'] = self.response
+ self.result['status'] = self.status
+ self.result['url'] = self.url
+ if self.stdout:
+ self.result['stdout'] = self.stdout
+
+ if 'state' in self.params:
+ self.original = self.existing
+ if self.params.get('state') in ('absent', 'present'):
+ self.get_existing()
+
+ # if self.module._diff and self.original != self.existing:
+ # self.result['diff'] = dict(
+ # before=json.dumps(self.original, sort_keys=True, indent=4),
+ # after=json.dumps(self.existing, sort_keys=True, indent=4),
+ # )
+ self.result['current'] = self.existing
+
+ if self.params.get('output_level') in ('debug', 'info'):
+ self.result['sent'] = self.config
+ self.result['proposed'] = self.proposed
+
+ self.result.update(**kwargs)
+ self.module.exit_json(**self.result)
+
+ def fail_json(self, msg, **kwargs):
+
+ # Return error information, if we have it
+ if self.error.get('code') is not None and self.error.get('text') is not None:
+ self.result['error'] = self.error
+
+ if 'state' in self.params:
+ if self.params.get('state') in ('absent', 'present'):
+ if self.params.get('output_level') in ('debug', 'info'):
+ self.result['previous'] = self.existing
+ if self.stdout:
+ self.result['stdout'] = self.stdout
+
+ # Return the gory details when we need it
+ if self.params.get('output_level') == 'debug':
+ if self.imdata is not None:
+ self.result['imdata'] = self.imdata
+ self.result['totalCount'] = self.totalCount
+
+ if self.params.get('output_level') == 'debug':
+ if self.url is not None:
+ if 'state' in self.params:
+ self.result['filter_string'] = self.filter_string
+ self.result['method'] = self.method
+ # self.result['path'] = self.path # Adding 'path' in result causes state: absent in output
+ self.result['response'] = self.response
+ self.result['status'] = self.status
+ self.result['url'] = self.url
+
+ if 'state' in self.params:
+ if self.params.get('output_level') in ('debug', 'info'):
+ self.result['sent'] = self.config
+ self.result['proposed'] = self.proposed
+
+ self.result.update(**kwargs)
+ self.module.fail_json(msg=msg, **self.result)
+
+ def dump_json(self):
+ if self.params.get('state') in ('absent', 'present'):
+ dn_path = (self.url).split('/mo/')[-1]
+ if dn_path[-5:] == '.json':
+ dn_path = dn_path[:-5]
+ mo = {}
+ if(self.proposed):
+ mo = self.proposed
+ for aci_class in mo:
+ mo[aci_class]['attributes']['dn'] = dn_path
+ if self.obj_filter is not None:
+ if 'tDn' in self.obj_filter:
+ mo[aci_class]['attributes']['tDn'] = self.obj_filter['tDn']
+
+ elif(self.params.get('state') == 'absent' and self.existing):
+ for aci_class in self.existing[0]:
+ mo[aci_class] = dict(attributes=dict(dn=dn_path, status="deleted"))
+
+ self.result['mo'] = mo
+ output_path = self.params.get('output_path')
+ if(output_path is not None):
+ with open(output_path, "a") as output_file:
+ json.dump([mo], output_file)
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user.py
new file mode 100644
index 00000000..a951ad4f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user.py
@@ -0,0 +1,367 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_aaa_user
+short_description: Manage AAA users (aaa:User)
+description:
+- Manage AAA users on Cisco ACI fabrics.
+requirements:
+- python-dateutil
+options:
+ aaa_password:
+ description:
+ - The password of the locally-authenticated user.
+ type: str
+ aaa_password_lifetime:
+ description:
+ - The lifetime of the locally-authenticated user password.
+ type: int
+ aaa_password_update_required:
+ description:
+ - Whether this account needs password update.
+ type: bool
+ aaa_user:
+ description:
+ - The name of the locally-authenticated user user to add.
+ type: str
+ aliases: [ name, user ]
+ clear_password_history:
+ description:
+ - Whether to clear the password history of a locally-authenticated user.
+ type: bool
+ description:
+ description:
+ - Description for the AAA user.
+ type: str
+ aliases: [ descr ]
+ email:
+ description:
+ - The email address of the locally-authenticated user.
+ type: str
+ enabled:
+ description:
+ - The status of the locally-authenticated user account.
+ type: bool
+ expiration:
+ description:
+ - The expiration date of the locally-authenticated user account.
+ type: str
+ expires:
+ description:
+ - Whether to enable an expiration date for the locally-authenticated user account.
+ type: bool
+ first_name:
+ description:
+ - The first name of the locally-authenticated user.
+ type: str
+ last_name:
+ description:
+ - The last name of the locally-authenticated user.
+ type: str
+ phone:
+ description:
+ - The phone number of the locally-authenticated user.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- This module is not idempotent when C(aaa_password) is being used
+ (even if that password was already set identically). This
+ appears to be an inconsistency wrt. the idempotent nature
+ of the APIC REST API. The vendor has been informed.
+ More information in :ref:`the ACI documentation <aci_guide_known_issues>`.
+seealso:
+- module: cisco.aci.aci_aaa_user_certificate
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(aaa:User).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add a user
+ cisco.aci.aci_aaa_user:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aaa_user: dag
+ aaa_password: AnotherSecretPassword
+ expiration: never
+ expires: no
+ email: dag@wieers.com
+ phone: 1-234-555-678
+ first_name: Dag
+ last_name: Wieers
+ state: present
+ delegate_to: localhost
+
+- name: Remove a user
+ cisco.aci.aci_aaa_user:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aaa_user: dag
+ state: absent
+ delegate_to: localhost
+
+- name: Query a user
+ cisco.aci.aci_aaa_user:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aaa_user: dag
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all users
+ cisco.aci.aci_aaa_user:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: '?rsp-prop-include=config-only'
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+try:
+ from dateutil.tz import tzutc
+ import dateutil.parser
+ HAS_DATEUTIL = True
+except ImportError:
+ HAS_DATEUTIL = False
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ aaa_password=dict(type='str', no_log=True),
+ aaa_password_lifetime=dict(type='int'),
+ aaa_password_update_required=dict(type='bool'),
+ aaa_user=dict(type='str', aliases=['name']), # Not required for querying all objects
+ clear_password_history=dict(type='bool'),
+ description=dict(type='str', aliases=['descr']),
+ email=dict(type='str'),
+ enabled=dict(type='bool'),
+ expiration=dict(type='str'),
+ expires=dict(type='bool'),
+ first_name=dict(type='str'),
+ last_name=dict(type='str'),
+ phone=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['aaa_user']],
+ ['state', 'present', ['aaa_user']],
+ ['expires', True, ['expiration']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ if not HAS_DATEUTIL:
+ module.fail_json(msg='dateutil required for this module')
+
+ aaa_password = module.params.get('aaa_password')
+ aaa_password_lifetime = module.params.get('aaa_password_lifetime')
+ aaa_password_update_required = aci.boolean(module.params.get('aaa_password_update_required'))
+ aaa_user = module.params.get('aaa_user')
+ clear_password_history = aci.boolean(module.params.get('clear_password_history'), 'yes', 'no')
+ description = module.params.get('description')
+ email = module.params.get('email')
+ enabled = aci.boolean(module.params.get('enabled'), 'active', 'inactive')
+ expires = aci.boolean(module.params.get('expires'))
+ first_name = module.params.get('first_name')
+ last_name = module.params.get('last_name')
+ phone = module.params.get('phone')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ expiration = module.params.get('expiration')
+ if expiration is not None and expiration != 'never':
+ try:
+ expiration = aci.iso8601_format(dateutil.parser.parse(expiration).replace(tzinfo=tzutc()))
+ except Exception as e:
+ module.fail_json(msg="Failed to parse date format '%s', %s" % (module.params.get('expiration'), e))
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='aaaUser',
+ aci_rn='userext/user-{0}'.format(aaa_user),
+ module_object=aaa_user,
+ target_filter={'name': aaa_user},
+ ),
+ )
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='aaaUser',
+ class_config=dict(
+ accountStatus=enabled,
+ clearPwdHistory=clear_password_history,
+ descr=description,
+ email=email,
+ expiration=expiration,
+ expires=expires,
+ firstName=first_name,
+ lastName=last_name,
+ name=aaa_user,
+ phone=phone,
+ pwd=aaa_password,
+ pwdLifeTime=aaa_password_lifetime,
+ pwdUpdateRequired=aaa_password_update_required,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='aaaUser')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user_certificate.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user_certificate.py
new file mode 100644
index 00000000..fc15e56f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aaa_user_certificate.py
@@ -0,0 +1,298 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_aaa_user_certificate
+short_description: Manage AAA user certificates (aaa:UserCert)
+description:
+- Manage AAA user certificates on Cisco ACI fabrics.
+options:
+ aaa_user:
+ description:
+ - The name of the user to add a certificate to.
+ type: str
+ required: yes
+ aaa_user_type:
+ description:
+ - Whether this is a normal user or an appuser.
+ type: str
+ choices: [ appuser, user ]
+ default: user
+ certificate:
+ description:
+ - The PEM format public key extracted from the X.509 certificate.
+ type: str
+ aliases: [ cert_data, certificate_data ]
+ certificate_name:
+ description:
+ - The name of the user certificate entry in ACI.
+ type: str
+ aliases: [ cert_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(aaa_user) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_aaa_user) module can be used for this.
+seealso:
+- module: cisco.aci.aci_aaa_user
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(aaa:UserCert).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add a certificate to user
+ cisco.aci.aci_aaa_user_certificate:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aaa_user: admin
+ certificate_name: admin
+ certificate_data: '{{ lookup("file", "pki/admin.crt") }}'
+ state: present
+ delegate_to: localhost
+
+- name: Remove a certificate of a user
+ cisco.aci.aci_aaa_user_certificate:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aaa_user: admin
+ certificate_name: admin
+ state: absent
+ delegate_to: localhost
+
+- name: Query a certificate of a user
+ cisco.aci.aci_aaa_user_certificate:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aaa_user: admin
+ certificate_name: admin
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all certificates of a user
+ cisco.aci.aci_aaa_user_certificate:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aaa_user: admin
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+ACI_MAPPING = dict(
+ appuser=dict(
+ aci_class='aaaAppUser',
+ aci_mo='userext/appuser-',
+ ),
+ user=dict(
+ aci_class='aaaUser',
+ aci_mo='userext/user-',
+ ),
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ aaa_user=dict(type='str', required=True),
+ aaa_user_type=dict(type='str', default='user', choices=['appuser', 'user']),
+ certificate=dict(type='str', aliases=['cert_data', 'certificate_data']),
+ certificate_name=dict(type='str', aliases=['cert_name']), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['aaa_user', 'certificate_name']],
+ ['state', 'present', ['aaa_user', 'certificate', 'certificate_name']],
+ ],
+ )
+
+ aaa_user = module.params.get('aaa_user')
+ aaa_user_type = module.params.get('aaa_user_type')
+ certificate = module.params.get('certificate')
+ certificate_name = module.params.get('certificate_name')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class=ACI_MAPPING.get(aaa_user_type).get('aci_class'),
+ aci_rn=ACI_MAPPING.get(aaa_user_type).get('aci_mo') + aaa_user,
+ module_object=aaa_user,
+ target_filter={'name': aaa_user},
+ ),
+ subclass_1=dict(
+ aci_class='aaaUserCert',
+ aci_rn='usercert-{0}'.format(certificate_name),
+ module_object=certificate_name,
+ target_filter={'name': certificate_name},
+ ),
+ )
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='aaaUserCert',
+ class_config=dict(
+ data=certificate,
+ name=certificate_name,
+ nameAlias=name_alias,
+
+ ),
+ )
+
+ aci.get_diff(aci_class='aaaUserCert')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py
new file mode 100644
index 00000000..246c82f4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_block_to_access_port.py
@@ -0,0 +1,437 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2018, Simon Metzger <smnmtzgr@gmail.com>
+# Copyright: (c) 2020, Shreyas Srish <ssrish@cisco.com>
+# Copyright: (c) 2020, Zak Lantz (@manofcolombia) <zakodewald@gmail.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_access_port_block_to_access_port
+short_description: Manage port blocks of Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:PortBlk)
+description:
+- Manage port blocks of Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics.
+options:
+ interface_profile:
+ description:
+ - The name of the Fabric access policy leaf interface profile.
+ type: str
+ aliases: [ leaf_interface_profile_name, leaf_interface_profile, interface_profile_name ]
+ access_port_selector:
+ description:
+ - The name of the Fabric access policy leaf interface profile access port selector.
+ type: str
+ aliases: [ name, access_port_selector_name ]
+ port_blk:
+ description:
+ - The name of the Fabric access policy leaf interface profile access port block.
+ type: str
+ aliases: [ leaf_port_blk_name, leaf_port_blk ]
+ port_blk_description:
+ description:
+ - The description to assign to the C(leaf_port_blk).
+ type: str
+ aliases: [ leaf_port_blk_description ]
+ from_port:
+ description:
+ - The beginning (from-range) of the port range block for the leaf access port block.
+ type: str
+ aliases: [ from, fromPort, from_port_range ]
+ to_port:
+ description:
+ - The end (to-range) of the port range block for the leaf access port block.
+ type: str
+ aliases: [ to, toPort, to_port_range ]
+ from_card:
+ description:
+ - The beginning (from-range) of the card range block for the leaf access port block.
+ type: str
+ aliases: [ from_card_range ]
+ to_card:
+ description:
+ - The end (to-range) of the card range block for the leaf access port block.
+ type: str
+ aliases: [ to_card_range ]
+ type:
+ description:
+ - The type of access port block to be created under respective access port.
+ type: str
+ choices: [ fex, leaf ]
+ default: leaf
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(interface_profile) and C(access_port_selector) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_interface_policy_leaf_profile) and M(cisco.aci.aci_access_port_to_interface_policy_leaf_profile) modules can be used for this.
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(infra:HPortS) and B(infra:PortBlk).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Simon Metzger (@smnmtzgr)
+'''
+
+EXAMPLES = r'''
+- name: Associate an access port block (single port) to an interface selector
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ port_blk: leafportblkname
+ from_port: 13
+ to_port: 13
+ state: present
+ delegate_to: localhost
+
+- name: Associate an access port block (port range) to an interface selector
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ port_blk: leafportblkname
+ from_port: 13
+ to_port: 16
+ state: present
+ delegate_to: localhost
+
+- name: Associate an access port block (single port) to an interface selector of type fex
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ type: fex
+ interface_profile: leafintprfname_fex
+ access_port_selector: accessportselectorname_fex
+ port_blk: leafportblkname_fex
+ from_port: 13
+ to_port: 13
+ state: present
+ delegate_to: localhost
+
+- name: Associate an access port block (port range) to an interface selector of type fex
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ type: fex
+ interface_profile: leafintprfname_fex
+ access_port_selector: accessportselectorname_fex
+ port_blk: leafportblkname_fex
+ from_port: 13
+ to_port: 16
+ state: present
+ delegate_to: localhost
+
+- name: Remove an access port block from an interface selector
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ port_blk: leafportblkname
+ from_port: 13
+ to_port: 13
+ state: absent
+ delegate_to: localhost
+
+- name: Remove an access port block from an interface selector of type fex
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ type: fex
+ interface_profile: leafintprfname_fex
+ access_port_selector: accessportselectorname_fex
+ port_blk: leafportblkname_fex
+ from_port: 13
+ to_port: 13
+ state: absent
+ delegate_to: localhost
+
+- name: Query Specific access port block under given access port selector
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ port_blk: leafportblkname
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query Specific access port block under given access port selector of type fex
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ type: fex
+ interface_profile: leafintprfname_fex
+ access_port_selector: accessportselectorname_fex
+ port_blk: leafportblkname_fex
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all access port blocks under given leaf interface profile
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all access port blocks under given leaf interface profile of type fex
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ type: fex
+ interface_profile: leafintprfname_fex
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all access port blocks in the fabric
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all access port blocks in the fabric of type fex
+ cisco.aci.aci_access_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ type: fex
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ interface_profile=dict(type='str', aliases=['leaf_interface_profile_name', 'leaf_interface_profile', 'interface_profile_name']),
+ access_port_selector=dict(type='str', aliases=['name', 'access_port_selector_name']), # Not required for querying all objects
+ port_blk=dict(type='str', aliases=['leaf_port_blk_name', 'leaf_port_blk']), # Not required for querying all objects
+ port_blk_description=dict(type='str', aliases=['leaf_port_blk_description']),
+ from_port=dict(type='str', aliases=['from', 'fromPort', 'from_port_range']),
+ to_port=dict(type='str', aliases=['to', 'toPort', 'to_port_range']),
+ from_card=dict(type='str', aliases=['from_card_range']),
+ to_card=dict(type='str', aliases=['to_card_range']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ type=dict(type='str', default='leaf', choices=['fex', 'leaf']), # This parameter is not required for querying all objects
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['access_port_selector', 'port_blk', 'interface_profile']],
+ ['state', 'present', ['access_port_selector', 'port_blk', 'from_port', 'to_port', 'interface_profile']],
+ ],
+ )
+
+ interface_profile = module.params.get('interface_profile')
+ access_port_selector = module.params.get('access_port_selector')
+ port_blk = module.params.get('port_blk')
+ port_blk_description = module.params.get('port_blk_description')
+ from_port = module.params.get('from_port')
+ to_port = module.params.get('to_port')
+ from_card = module.params.get('from_card')
+ to_card = module.params.get('to_card')
+ state = module.params.get('state')
+ type_port = module.params.get('type')
+
+ aci = ACIModule(module)
+ aci_class = 'infraAccPortP'
+ aci_rn = 'accportprof'
+ if type_port == 'fex':
+ aci_class = 'infraFexP'
+ aci_rn = 'fexprof'
+ aci.construct_url(
+ root_class=dict(
+ aci_class=aci_class,
+ aci_rn='infra/' + aci_rn + '-{0}'.format(interface_profile),
+ module_object=interface_profile,
+ target_filter={'name': interface_profile},
+ ),
+ subclass_1=dict(
+ aci_class='infraHPortS',
+ # NOTE: normal rn: hports-{name}-typ-{type}, hence here hardcoded to range for purposes of module
+ aci_rn='hports-{0}-typ-range'.format(access_port_selector),
+ module_object=access_port_selector,
+ target_filter={'name': access_port_selector},
+ ),
+ subclass_2=dict(
+ aci_class='infraPortBlk',
+ aci_rn='portblk-{0}'.format(port_blk),
+ module_object=port_blk,
+ target_filter={'name': port_blk},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraPortBlk',
+ class_config=dict(
+ descr=port_blk_description,
+ name=port_blk,
+ fromPort=from_port,
+ toPort=to_port,
+ fromCard=from_card,
+ toCard=to_card,
+ # type='range',
+ ),
+ )
+
+ aci.get_diff(aci_class='infraPortBlk')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py
new file mode 100644
index 00000000..f419c8b9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_port_to_interface_policy_leaf_profile.py
@@ -0,0 +1,429 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Bruno Calogero <brunocalogero@hotmail.com>
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_access_port_to_interface_policy_leaf_profile
+short_description: Manage Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:RsAccBaseGrp, infra:PortBlk)
+description:
+- Manage Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics.
+options:
+ interface_profile:
+ description:
+ - The name of the Fabric access policy leaf interface profile.
+ type: str
+ aliases: [ leaf_interface_profile_name, leaf_interface_profile, interface_profile_name ]
+ access_port_selector:
+ description:
+ - The name of the Fabric access policy leaf interface profile access port selector.
+ type: str
+ aliases: [ name, access_port_selector_name ]
+ description:
+ description:
+ - The description to assign to the C(access_port_selector)
+ type: str
+ port_blk:
+ description:
+ - B(Deprecated)
+ - Starting with Ansible 2.8 we recommend using M(cisco.aci.aci_access_port_block_to_access_port) instead.
+ - The parameter will be removed in Ansible 2.12.
+ - HORIZONTALLINE
+ - The name of the Fabric access policy leaf interface profile access port block.
+ type: str
+ aliases: [ leaf_port_blk_name, leaf_port_blk, port_blk_name ]
+ leaf_port_blk_description:
+ description:
+ - B(Deprecated)
+ - Starting with Ansible 2.8 we recommend using M(cisco.aci.aci_access_port_block_to_access_port) instead.
+ - The parameter will be removed in Ansible 2.12.
+ - HORIZONTALLINE
+ - The description to assign to the C(leaf_port_blk)
+ type: str
+ from_port:
+ description:
+ - B(Deprecated)
+ - Starting with Ansible 2.8 we recommend using M(cisco.aci.aci_access_port_block_to_access_port) instead.
+ - The parameter will be removed in Ansible 2.12.
+ - HORIZONTALLINE
+ - The beginning (from-range) of the port range block for the leaf access port block.
+ type: str
+ aliases: [ from, fromPort, from_port_range ]
+ to_port:
+ description:
+ - B(Deprecated)
+ - Starting with Ansible 2.8 we recommend using M(cisco.aci.aci_access_port_block_to_access_port) instead.
+ - The parameter will be removed in Ansible 2.12.
+ - HORIZONTALLINE
+ - The end (to-range) of the port range block for the leaf access port block.
+ type: str
+ aliases: [ to, toPort, to_port_range ]
+ from_card:
+ description:
+ - B(Deprecated)
+ - Starting with Ansible 2.8 we recommend using M(cisco.aci.aci_access_port_block_to_access_port) instead.
+ - The parameter will be removed in Ansible 2.12.
+ - HORIZONTALLINE
+ - The beginning (from-range) of the card range block for the leaf access port block.
+ type: str
+ aliases: [ from_card_range ]
+ to_card:
+ description:
+ - B(Deprecated)
+ - Starting with Ansible 2.8 we recommend using M(cisco.aci.aci_access_port_block_to_access_port) instead.
+ - The parameter will be removed in Ansible 2.12.
+ - HORIZONTALLINE
+ - The end (to-range) of the card range block for the leaf access port block.
+ type: str
+ aliases: [ to_card_range ]
+ policy_group:
+ description:
+ - The name of the fabric access policy group to be associated with the leaf interface profile interface selector.
+ type: str
+ aliases: [ policy_group_name ]
+ interface_type:
+ description:
+ - The type of interface for the static EPG deployment.
+ type: str
+ choices: [ breakout, fex, port_channel, switch_port, vpc ]
+ default: switch_port
+ type:
+ description:
+ - The type of access port to be created under respective profile.
+ type: str
+ choices: [ fex, leaf ]
+ default: leaf
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(interface_profile) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_interface_policy_leaf_profile) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_access_port_block_to_access_port
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(infra:HPortS), B(infra:RsAccBaseGrp) and B(infra:PortBlk).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Associate an Interface Access Port Selector to an Interface Policy Leaf Profile with a Policy Group
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ port_blk: leafportblkname
+ from_port: 13
+ to_port: 16
+ policy_group: policygroupname
+ state: present
+ delegate_to: localhost
+
+- name: Associate an interface access port selector to an Interface Policy Leaf Profile (w/o policy group) (check if this works)
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ port_blk: leafportblkname
+ from_port: 13
+ to_port: 16
+ state: present
+ delegate_to: localhost
+
+- name: Remove an interface access port selector associated with an Interface Policy Leaf Profile
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ state: absent
+ delegate_to: localhost
+
+- name: Remove an interface access port selector associated with an Interface Policy Fex Profile
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: fexintprfname
+ access_port_selector: accessportselectorname
+ state: absent
+ delegate_to: localhost
+
+- name: Query Specific access_port_selector under given leaf_interface_profile
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query Specific access_port_selector under given Fex leaf_interface_profile
+ cisco.aci.aci_access_port_to_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: fexintprfname
+ access_port_selector: accessportselectorname
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+INTERFACE_TYPE_MAPPING = dict(
+ breakout='uni/infra/funcprof/brkoutportgrp-{0}',
+ fex='uni/infra/funcprof/accportgrp-{0}',
+ port_channel='uni/infra/funcprof/accbundle-{0}',
+ switch_port='uni/infra/funcprof/accportgrp-{0}',
+ vpc='uni/infra/funcprof/accbundle-{0}',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ interface_profile=dict(type='str', aliases=['leaf_interface_profile_name', 'leaf_interface_profile', 'interface_profile_name']),
+ access_port_selector=dict(type='str', aliases=['name', 'access_port_selector_name']), # Not required for querying all objects
+ description=dict(type='str'),
+ port_blk=dict(type='str', aliases=['leaf_port_blk_name', 'leaf_port_blk', 'port_blk_name']),
+ leaf_port_blk_description=dict(type='str'),
+ from_port=dict(type='str', aliases=['from', 'fromPort', 'from_port_range']),
+ to_port=dict(type='str', aliases=['to', 'toPort', 'to_port_range']),
+ from_card=dict(type='str', aliases=['from_card_range']),
+ to_card=dict(type='str', aliases=['to_card_range']),
+ policy_group=dict(type='str', aliases=['policy_group_name']),
+ interface_type=dict(type='str', default='switch_port', choices=['breakout', 'fex', 'port_channel', 'switch_port', 'vpc']),
+ type=dict(type='str', default='leaf', choices=['fex', 'leaf']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['interface_profile', 'access_port_selector']],
+ ['state', 'present', ['interface_profile', 'access_port_selector']],
+ ],
+ )
+
+ interface_profile = module.params.get('interface_profile')
+ access_port_selector = module.params.get('access_port_selector')
+ description = module.params.get('description')
+ port_blk = module.params.get('port_blk')
+ leaf_port_blk_description = module.params.get('leaf_port_blk_description')
+ from_port = module.params.get('from_port')
+ to_port = module.params.get('to_port')
+ from_card = module.params.get('from_card')
+ to_card = module.params.get('to_card')
+ policy_group = module.params.get('policy_group')
+ interface_type = module.params.get('interface_type')
+ state = module.params.get('state')
+ type_profile = module.params.get('type')
+
+ # Build child_configs dynamically
+ child_configs = [dict(
+ infraPortBlk=dict(
+ attributes=dict(
+ descr=leaf_port_blk_description,
+ name=port_blk,
+ fromPort=from_port,
+ toPort=to_port,
+ fromCard=from_card,
+ toCard=to_card,
+ ),
+ ),
+ )]
+
+ # Add infraRsAccBaseGrp only when policy_group was defined
+ if policy_group is not None:
+ child_configs.append(dict(
+ infraRsAccBaseGrp=dict(
+ attributes=dict(
+ tDn=INTERFACE_TYPE_MAPPING[interface_type].format(policy_group),
+ ),
+ ),
+ ))
+
+ aci = ACIModule(module)
+ aci_class = 'infraAccPortP'
+ aci_rn = 'accportprof'
+ if type_profile == 'fex':
+ aci_class = 'infraFexP'
+ aci_rn = 'fexprof'
+ aci.construct_url(
+ root_class=dict(
+ aci_class=aci_class,
+ aci_rn='infra/' + aci_rn + '-{0}'.format(interface_profile),
+ module_object=interface_profile,
+ target_filter={'name': interface_profile},
+ ),
+ subclass_1=dict(
+ aci_class='infraHPortS',
+ # NOTE: normal rn: hports-{name}-typ-{type}, hence here hardcoded to range for purposes of module
+ aci_rn='hports-{0}-typ-range'.format(access_port_selector),
+ module_object=access_port_selector,
+ target_filter={'name': access_port_selector},
+ ),
+ child_classes=['infraPortBlk', 'infraRsAccBaseGrp'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraHPortS',
+ class_config=dict(
+ descr=description,
+ name=access_port_selector,
+ # type='range',
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='infraHPortS')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py
new file mode 100644
index 00000000..7cbfdeab
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_access_sub_port_block_to_access_port.py
@@ -0,0 +1,364 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2019, Simon Metzger <smnmtzgr@gmail.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_access_sub_port_block_to_access_port
+short_description: Manage sub port blocks of Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:SubPortBlk)
+description:
+- Manage sub port blocks of Fabric interface policy leaf profile interface selectors on Cisco ACI fabrics.
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(infra:HPortS) and B(infra:SubPortBlk).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Simon Metzger (@smnmtzgr)
+options:
+ leaf_interface_profile:
+ description:
+ - The name of the Fabric access policy leaf interface profile.
+ type: str
+ aliases: [ leaf_interface_profile_name ]
+ access_port_selector:
+ description:
+ - The name of the Fabric access policy leaf interface profile access port selector.
+ type: str
+ aliases: [ name, access_port_selector_name ]
+ leaf_port_blk:
+ description:
+ - The name of the Fabric access policy leaf interface profile access port block.
+ type: str
+ aliases: [ leaf_port_blk_name ]
+ leaf_port_blk_description:
+ description:
+ - The description to assign to the C(leaf_port_blk).
+ type: str
+ from_port:
+ description:
+ - The beginning (from-range) of the port range block for the leaf access port block.
+ type: str
+ aliases: [ from, fromPort, from_port_range ]
+ to_port:
+ description:
+ - The end (to-range) of the port range block for the leaf access port block.
+ type: str
+ aliases: [ to, toPort, to_port_range ]
+ from_sub_port:
+ description:
+ - The beginning (from-range) of the sub port range block for the leaf access port block.
+ type: str
+ aliases: [ fromSubPort, from_sub_port_range ]
+ to_sub_port:
+ description:
+ - The end (to-range) of the sub port range block for the leaf access port block.
+ type: str
+ aliases: [ toSubPort, to_sub_port_range ]
+ from_card:
+ description:
+ - The beginning (from-range) of the card range block for the leaf access port block.
+ type: str
+ aliases: [ from_card_range ]
+ to_card:
+ description:
+ - The end (to-range) of the card range block for the leaf access port block.
+ type: str
+ aliases: [ to_card_range ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+'''
+
+EXAMPLES = r'''
+- name: Associate an access sub port block (single port) to an interface selector
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ leaf_port_blk: leafportblkname
+ from_port: 13
+ to_port: 13
+ from_sub_port: 1
+ to_sub_port: 1
+ state: present
+ delegate_to: localhost
+
+- name: Associate an access sub port block (port range) to an interface selector
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ leaf_port_blk: leafportblkname
+ from_port: 13
+ to_port: 13
+ from_sub_port: 1
+ to_sub_port: 3
+ state: present
+ delegate_to: localhost
+
+- name: Remove an access sub port block from an interface selector
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ leaf_port_blk: leafportblkname
+ from_port: 13
+ to_port: 13
+ from_sub_port: 1
+ to_sub_port: 1
+ state: absent
+ delegate_to: localhost
+
+- name: Query Specific access sub port block under given access port selector
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_interface_profile: leafintprfname
+ access_port_selector: accessportselectorname
+ leaf_port_blk: leafportblkname
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all access sub port blocks under given leaf interface profile
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_interface_profile: leafintprfname
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all access sub port blocks in the fabric
+ cisco.aci.aci_access_sub_port_block_to_access_port:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ leaf_interface_profile=dict(type='str', aliases=['leaf_interface_profile_name']), # Not required for querying all objects
+ access_port_selector=dict(type='str', aliases=['name', 'access_port_selector_name']), # Not required for querying all objects
+ leaf_port_blk=dict(type='str', aliases=['leaf_port_blk_name']), # Not required for querying all objects
+ leaf_port_blk_description=dict(type='str'),
+ from_port=dict(type='str', aliases=['from', 'fromPort', 'from_port_range']), # Not required for querying all objects and deleting sub port blocks
+ to_port=dict(type='str', aliases=['to', 'toPort', 'to_port_range']), # Not required for querying all objects and deleting sub port blocks
+ from_sub_port=dict(type='str', aliases=['fromSubPort', 'from_sub_port_range']), # Not required for querying all objects and deleting sub port blocks
+ to_sub_port=dict(type='str', aliases=['toSubPort', 'to_sub_port_range']), # Not required for querying all objects and deleting sub port blocks
+ from_card=dict(type='str', aliases=['from_card_range']),
+ to_card=dict(type='str', aliases=['to_card_range']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['access_port_selector', 'leaf_port_blk', 'leaf_interface_profile']],
+ ['state', 'present', ['access_port_selector', 'leaf_port_blk', 'from_port', 'to_port', 'from_sub_port', 'to_sub_port', 'leaf_interface_profile']],
+ ],
+ )
+
+ leaf_interface_profile = module.params.get('leaf_interface_profile')
+ access_port_selector = module.params.get('access_port_selector')
+ leaf_port_blk = module.params.get('leaf_port_blk')
+ leaf_port_blk_description = module.params.get('leaf_port_blk_description')
+ from_port = module.params.get('from_port')
+ to_port = module.params.get('to_port')
+ from_sub_port = module.params.get('from_sub_port')
+ to_sub_port = module.params.get('to_sub_port')
+ from_card = module.params.get('from_card')
+ to_card = module.params.get('to_card')
+ state = module.params.get('state')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='infraAccPortP',
+ aci_rn='infra/accportprof-{0}'.format(leaf_interface_profile),
+ module_object=leaf_interface_profile,
+ target_filter={'name': leaf_interface_profile},
+ ),
+ subclass_1=dict(
+ aci_class='infraHPortS',
+ # NOTE: normal rn: hports-{name}-typ-{type}, hence here hardcoded to range for purposes of module
+ aci_rn='hports-{0}-typ-range'.format(access_port_selector),
+ module_object=access_port_selector,
+ target_filter={'name': access_port_selector},
+ ),
+ subclass_2=dict(
+ aci_class='infraSubPortBlk',
+ aci_rn='subportblk-{0}'.format(leaf_port_blk),
+ module_object=leaf_port_blk,
+ target_filter={'name': leaf_port_blk},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraSubPortBlk',
+ class_config=dict(
+ descr=leaf_port_blk_description,
+ name=leaf_port_blk,
+ fromPort=from_port,
+ toPort=to_port,
+ fromSubPort=from_sub_port,
+ toSubPort=to_sub_port,
+ fromCard=from_card,
+ toCard=to_card,
+ # type='range',
+ ),
+ )
+
+ aci.get_diff(aci_class='infraSubPortBlk')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep.py
new file mode 100644
index 00000000..29db95a5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep.py
@@ -0,0 +1,286 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_aep
+short_description: Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP, infra:ProvAcc)
+description:
+- Connect to external virtual and physical domains by using
+ attachable Access Entity Profiles (AEP) on Cisco ACI fabrics.
+options:
+ aep:
+ description:
+ - The name of the Attachable Access Entity Profile.
+ type: str
+ aliases: [ aep_name, name ]
+ description:
+ description:
+ - Description for the AEP.
+ type: str
+ aliases: [ descr ]
+ infra_vlan:
+ description:
+ - Enable infrastructure VLAN.
+ - The hypervisor functions of the AEP.
+ - C(no) will disable the infrastructure vlan if it is enabled.
+ type: bool
+ aliases: [ infrastructure_vlan ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ default: present
+ choices: [ absent, present, query ]
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_aep_to_domain
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(infra:AttEntityP) and B(infra:ProvAcc).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Swetha Chunduri (@schunduri)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Add a new AEP
+ cisco.aci.aci_aep:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aep: ACI-AEP
+ description: default
+ infra_vlan: true
+ state: present
+ delegate_to: localhost
+
+- name: Remove an existing AEP
+ cisco.aci.aci_aep:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aep: ACI-AEP
+ state: absent
+ delegate_to: localhost
+
+- name: Query all AEPs
+ cisco.aci.aci_aep:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a specific AEP
+ cisco.aci.aci_aep:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aep: ACI-AEP
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ aep=dict(type='str', aliases=['name', 'aep_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ infra_vlan=dict(type='bool', aliases=['infrastructure_vlan']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['aep']],
+ ['state', 'present', ['aep']],
+ ],
+ )
+
+ aep = module.params.get('aep')
+ description = module.params.get('description')
+ infra_vlan = module.params.get('infra_vlan')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+ if infra_vlan:
+ child_configs = [dict(infraProvAcc=dict(attributes=dict(name='provacc')))]
+ elif infra_vlan is False:
+ child_configs = [dict(infraProvAcc=dict(attributes=dict(name='provacc', status='deleted')))]
+ else:
+ child_configs = []
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='infraAttEntityP',
+ aci_rn='infra/attentp-{0}'.format(aep),
+ module_object=aep,
+ target_filter={'name': aep},
+ ),
+ child_classes=['infraProvAcc']
+ )
+
+ aci.get_existing()
+
+ try:
+ if len(aci.existing[0]['infraAttEntityP']) == 1 and infra_vlan is False:
+ child_configs = []
+ except Exception:
+ pass
+
+ if state == 'present':
+
+ aci.payload(
+ aci_class='infraAttEntityP',
+ class_config=dict(
+ name=aep,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='infraAttEntityP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_domain.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_domain.py
new file mode 100644
index 00000000..716906d0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_aep_to_domain.py
@@ -0,0 +1,313 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Dag Wieers <dag@wieers.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_aep_to_domain
+short_description: Bind AEPs to Physical or Virtual Domains (infra:RsDomP)
+description:
+- Bind AEPs to Physical or Virtual Domains on Cisco ACI fabrics.
+options:
+ aep:
+ description:
+ - The name of the Attachable Access Entity Profile.
+ type: str
+ aliases: [ aep_name ]
+ domain:
+ description:
+ - Name of the physical or virtual domain being associated with the AEP.
+ type: str
+ aliases: [ domain_name, domain_profile ]
+ domain_type:
+ description:
+ - Determines if the Domain is physical (phys) or virtual (vmm).
+ type: str
+ choices: [ fc, l2dom, l3dom, phys, vmm ]
+ aliases: [ type ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ vm_provider:
+ description:
+ - The VM platform for VMM Domains.
+ - Support for Kubernetes was added in ACI v3.0.
+ - Support for CloudFoundry, OpenShift and Red Hat was added in ACI v3.1.
+ type: str
+ choices: [ cloudfoundry, kubernetes, microsoft, openshift, openstack, redhat, vmware ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(aep) and C(domain) parameters should exist before using this module.
+ The M(cisco.aci.aci_aep) and M(cisco.aci.aci_domain) can be used for these.
+seealso:
+- module: cisco.aci.aci_aep
+- module: cisco.aci.aci_domain
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(infra:RsDomP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add AEP to domain binding
+ cisco.aci.aci_aep_to_domain: &binding_present
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ state: present
+ delegate_to: localhost
+
+- name: Remove AEP to domain binding
+ cisco.aci.aci_aep_to_domain: &binding_absent
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ state: absent
+ delegate_to: localhost
+
+- name: Query our AEP to domain binding
+ cisco.aci.aci_aep_to_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ aep: test_aep
+ domain: phys_dom
+ domain_type: phys
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all AEP to domain bindings
+ cisco.aci.aci_aep_to_domain: &binding_query
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+VM_PROVIDER_MAPPING = dict(
+ cloudfoundry='CloudFoundry',
+ kubernetes='Kubernetes',
+ microsoft='Microsoft',
+ openshift='OpenShift',
+ openstack='OpenStack',
+ redhat='Redhat',
+ vmware='VMware',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ aep=dict(type='str', aliases=['aep_name']), # Not required for querying all objects
+ domain=dict(type='str', aliases=['domain_name', 'domain_profile']), # Not required for querying all objects
+ domain_type=dict(type='str', choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm'], aliases=['type']), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['domain_type', 'vmm', ['vm_provider']],
+ ['state', 'absent', ['aep', 'domain', 'domain_type']],
+ ['state', 'present', ['aep', 'domain', 'domain_type']],
+ ],
+ required_together=[
+ ['domain', 'domain_type'],
+ ],
+ )
+
+ aep = module.params.get('aep')
+ domain = module.params.get('domain')
+ domain_type = module.params.get('domain_type')
+ vm_provider = module.params.get('vm_provider')
+ state = module.params.get('state')
+
+ # Report when vm_provider is set when type is not virtual
+ if domain_type != 'vmm' and vm_provider is not None:
+ module.fail_json(msg="Domain type '{0}' cannot have a 'vm_provider'".format(domain_type))
+
+ # Compile the full domain for URL building
+ if domain_type == 'fc':
+ domain_mo = 'uni/fc-{0}'.format(domain)
+ elif domain_type == 'l2dom':
+ domain_mo = 'uni/l2dom-{0}'.format(domain)
+ elif domain_type == 'l3dom':
+ domain_mo = 'uni/l3dom-{0}'.format(domain)
+ elif domain_type == 'phys':
+ domain_mo = 'uni/phys-{0}'.format(domain)
+ elif domain_type == 'vmm':
+ domain_mo = 'uni/vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
+ else:
+ domain_mo = None
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='infraAttEntityP',
+ aci_rn='infra/attentp-{0}'.format(aep),
+ module_object=aep,
+ target_filter={'name': aep},
+ ),
+ subclass_1=dict(
+ aci_class='infraRsDomP',
+ aci_rn='rsdomP-[{0}]'.format(domain_mo),
+ module_object=domain_mo,
+ target_filter={'tDn': domain_mo},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraRsDomP',
+ class_config=dict(tDn=domain_mo),
+ )
+
+ aci.get_diff(aci_class='infraRsDomP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_ap.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_ap.py
new file mode 100644
index 00000000..0c10fbd4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_ap.py
@@ -0,0 +1,290 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_ap
+short_description: Manage top level Application Profile (AP) objects (fv:Ap)
+description:
+- Manage top level Application Profile (AP) objects on Cisco ACI fabrics
+options:
+ tenant:
+ description:
+ - The name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ ap:
+ description:
+ - The name of the application network profile.
+ type: str
+ aliases: [ app_profile, app_profile_name, name ]
+ description:
+ description:
+ - Description for the AP.
+ type: str
+ aliases: [ descr ]
+ monitoring_policy:
+ description:
+ - The name of the monitoring policy.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- This module does not manage EPGs, see M(cisco.aci.aci_epg) to do this.
+- The used C(tenant) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:Ap).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Swetha Chunduri (@schunduri)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Add a new AP
+ cisco.aci.aci_ap:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ap: default
+ description: default ap
+ monitoring_policy: default
+ state: present
+ delegate_to: localhost
+
+- name: Remove an AP
+ cisco.aci.aci_ap:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ap: default
+ state: absent
+ delegate_to: localhost
+
+- name: Query an AP
+ cisco.aci.aci_ap:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ap: default
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all APs
+ cisco.aci.aci_ap:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ ap=dict(type='str', aliases=['app_profile', 'app_profile_name', 'name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ monitoring_policy=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['tenant', 'ap']],
+ ['state', 'present', ['tenant', 'ap']],
+ ],
+ )
+
+ ap = module.params.get('ap')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+ monitoring_policy = module.params.get('monitoring_policy')
+
+ child_configs = [dict(fvRsApMonPol=dict(attributes=dict(tnMonEPGPolName=monitoring_policy)))]
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvAp',
+ aci_rn='ap-{0}'.format(ap),
+ module_object=ap,
+ target_filter={'name': ap},
+ ),
+ child_classes=['fvRsApMonPol'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvAp',
+ class_config=dict(
+ name=ap,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='fvAp')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd.py
new file mode 100644
index 00000000..02ba1aeb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd.py
@@ -0,0 +1,461 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_bd
+short_description: Manage Bridge Domains (BD) objects (fv:BD)
+description:
+- Manages Bridge Domains (BD) on Cisco ACI fabrics.
+options:
+ arp_flooding:
+ description:
+ - Determines if the Bridge Domain should flood ARP traffic.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ bd:
+ description:
+ - The name of the Bridge Domain.
+ type: str
+ aliases: [ bd_name, name ]
+ bd_type:
+ description:
+ - The type of traffic on the Bridge Domain.
+ - The APIC defaults to C(ethernet) when unset during creation.
+ type: str
+ choices: [ ethernet, fc ]
+ description:
+ description:
+ - Description for the Bridge Domain.
+ type: str
+ enable_multicast:
+ description:
+ - Determines if PIM is enabled.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ enable_routing:
+ description:
+ - Determines if IP forwarding should be allowed.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ endpoint_clear:
+ description:
+ - Clears all End Points in all Leaves when C(yes).
+ - The value is not reset to disabled once End Points have been cleared; that requires a second task.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ endpoint_move_detect:
+ description:
+ - Determines if GARP should be enabled to detect when End Points move.
+ - The APIC defaults to C(garp) when unset during creation.
+ type: str
+ choices: [ default, garp ]
+ endpoint_retention_action:
+ description:
+ - Determines if the Bridge Domain should inherit or resolve the End Point Retention Policy.
+ - The APIC defaults to C(resolve) when unset during creation.
+ type: str
+ choices: [ inherit, resolve ]
+ endpoint_retention_policy:
+ description:
+ - The name of the End Point Retention Policy the Bridge Domain should use when
+ overriding the default End Point Retention Policy.
+ type: str
+ igmp_snoop_policy:
+ description:
+ - The name of the IGMP Snooping Policy the Bridge Domain should use when
+ overriding the default IGMP Snooping Policy.
+ type: str
+ ip_learning:
+ description:
+ - Determines if the Bridge Domain should learn End Point IPs.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ ipv6_nd_policy:
+ description:
+ - The name of the IPv6 Neighbor Discovery Policy the Bridge Domain should use when
+ overridding the default IPV6 ND Policy.
+ type: str
+ l2_unknown_unicast:
+ description:
+ - Determines what forwarding method to use for unknown l2 destinations.
+ - The APIC defaults to C(proxy) when unset during creation.
+ type: str
+ choices: [ proxy, flood ]
+ l3_unknown_multicast:
+ description:
+ - Determines the forwarding method to use for unknown multicast destinations.
+ - The APIC defaults to C(flood) when unset during creation.
+ type: str
+ choices: [ flood, opt-flood ]
+ limit_ip_learn:
+ description:
+ - Determines if the BD should limit IP learning to only subnets owned by the Bridge Domain.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ mac_address:
+ description:
+ - The MAC Address to assign to the C(bd) instead of using the default.
+ - The APIC defaults to C(00:22:BD:F8:19:FF) when unset during creation.
+ type: str
+ aliases: [ mac ]
+ multi_dest:
+ description:
+ - Determines the forwarding method for L2 multicast, broadcast, and link layer traffic.
+ - The APIC defaults to C(bd-flood) when unset during creation.
+ type: str
+ choices: [ bd-flood, drop, encap-flood ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ aliases: [ tenant_name ]
+ vrf:
+ description:
+ - The name of the VRF.
+ type: str
+ aliases: [ vrf_name ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:BD).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Add Bridge Domain
+ cisco.aci.aci_bd:
+ host: "{{ inventory_hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: no
+ tenant: prod
+ bd: web_servers
+ mac_address: 00:22:BD:F8:19:FE
+ vrf: prod_vrf
+ state: present
+ delegate_to: localhost
+
+- name: Add an FC Bridge Domain
+ cisco.aci.aci_bd:
+ host: "{{ inventory_hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: no
+ tenant: prod
+ bd: storage
+ bd_type: fc
+ vrf: fc_vrf
+ enable_routing: no
+ state: present
+ delegate_to: localhost
+
+- name: Modify a Bridge Domain
+ cisco.aci.aci_bd:
+ host: "{{ inventory_hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: yes
+ tenant: prod
+ bd: web_servers
+ arp_flooding: yes
+ l2_unknown_unicast: flood
+ state: present
+ delegate_to: localhost
+
+- name: Query All Bridge Domains
+ cisco.aci.aci_bd:
+ host: "{{ inventory_hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: yes
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a Bridge Domain
+ cisco.aci.aci_bd:
+ host: "{{ inventory_hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: yes
+ tenant: prod
+ bd: web_servers
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Delete a Bridge Domain
+ cisco.aci.aci_bd:
+ host: "{{ inventory_hostname }}"
+ username: "{{ username }}"
+ password: "{{ password }}"
+ validate_certs: yes
+ tenant: prod
+ bd: web_servers
+ state: absent
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ arp_flooding=dict(type='bool'),
+ bd=dict(type='str', aliases=['bd_name', 'name']), # Not required for querying all objects
+ bd_type=dict(type='str', choices=['ethernet', 'fc']),
+ description=dict(type='str'),
+ enable_multicast=dict(type='bool'),
+ enable_routing=dict(type='bool'),
+ endpoint_clear=dict(type='bool'),
+ endpoint_move_detect=dict(type='str', choices=['default', 'garp']),
+ endpoint_retention_action=dict(type='str', choices=['inherit', 'resolve']),
+ endpoint_retention_policy=dict(type='str'),
+ igmp_snoop_policy=dict(type='str'),
+ ip_learning=dict(type='bool'),
+ ipv6_nd_policy=dict(type='str'),
+ l2_unknown_unicast=dict(type='str', choices=['proxy', 'flood']),
+ l3_unknown_multicast=dict(type='str', choices=['flood', 'opt-flood']),
+ limit_ip_learn=dict(type='bool'),
+ mac_address=dict(type='str', aliases=['mac']),
+ multi_dest=dict(type='str', choices=['bd-flood', 'drop', 'encap-flood']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ vrf=dict(type='str', aliases=['vrf_name']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['bd', 'tenant']],
+ ['state', 'present', ['bd', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ arp_flooding = aci.boolean(module.params.get('arp_flooding'))
+ bd = module.params.get('bd')
+ bd_type = module.params.get('bd_type')
+ if bd_type == 'ethernet':
+ # ethernet type is represented as regular, but that is not clear to the users
+ bd_type = 'regular'
+ description = module.params.get('description')
+ enable_multicast = aci.boolean(module.params.get('enable_multicast'))
+ enable_routing = aci.boolean(module.params.get('enable_routing'))
+ endpoint_clear = aci.boolean(module.params.get('endpoint_clear'))
+ endpoint_move_detect = module.params.get('endpoint_move_detect')
+ if endpoint_move_detect == 'default':
+ # the ACI default setting is an empty string, but that is not a good input value
+ endpoint_move_detect = ''
+ endpoint_retention_action = module.params.get('endpoint_retention_action')
+ endpoint_retention_policy = module.params.get('endpoint_retention_policy')
+ igmp_snoop_policy = module.params.get('igmp_snoop_policy')
+ ip_learning = aci.boolean(module.params.get('ip_learning'))
+ ipv6_nd_policy = module.params.get('ipv6_nd_policy')
+ l2_unknown_unicast = module.params.get('l2_unknown_unicast')
+ l3_unknown_multicast = module.params.get('l3_unknown_multicast')
+ limit_ip_learn = aci.boolean(module.params.get('limit_ip_learn'))
+ mac_address = module.params.get('mac_address')
+ multi_dest = module.params.get('multi_dest')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ vrf = module.params.get('vrf')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvBD',
+ aci_rn='BD-{0}'.format(bd),
+ module_object=bd,
+ target_filter={'name': bd},
+ ),
+ child_classes=['fvRsCtx', 'fvRsIgmpsn', 'fvRsBDToNdP', 'fvRsBdToEpRet'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvBD',
+ class_config=dict(
+ arpFlood=arp_flooding,
+ descr=description,
+ epClear=endpoint_clear,
+ epMoveDetectMode=endpoint_move_detect,
+ ipLearning=ip_learning,
+ limitIpLearnToSubnets=limit_ip_learn,
+ mac=mac_address,
+ mcastAllow=enable_multicast,
+ multiDstPktAct=multi_dest,
+ name=bd,
+ type=bd_type,
+ unicastRoute=enable_routing,
+ unkMacUcastAct=l2_unknown_unicast,
+ unkMcastAct=l3_unknown_multicast,
+ nameAlias=name_alias,
+ ),
+ child_configs=[
+ {'fvRsCtx': {'attributes': {'tnFvCtxName': vrf}}},
+ {'fvRsIgmpsn': {'attributes': {'tnIgmpSnoopPolName': igmp_snoop_policy}}},
+ {'fvRsBDToNdP': {'attributes': {'tnNdIfPolName': ipv6_nd_policy}}},
+ {'fvRsBdToEpRet': {'attributes': {'resolveAct': endpoint_retention_action, 'tnFvEpRetPolName': endpoint_retention_policy}}},
+ ],
+ )
+
+ aci.get_diff(aci_class='fvBD')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_dhcp_label.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_dhcp_label.py
new file mode 100644
index 00000000..7b226200
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_dhcp_label.py
@@ -0,0 +1,312 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Dag Wieers (@dagwieers)
+# Copyright: (c) 2020, sig9org (@sig9org)
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'}
+
+DOCUMENTATION = r'''
+---
+module: aci_bd_dhcp_label
+short_description: Manage DHCP Labels (dhcp:Lbl)
+description:
+- Manage DHCP Labels on Cisco ACI fabrics.
+options:
+ bd:
+ description:
+ - The name of the Bridge Domain.
+ type: str
+ aliases: [ bd_name ]
+ description:
+ description:
+ - The description for the DHCP Label.
+ type: str
+ aliases: [ descr ]
+ dhcp_label:
+ description:
+ - The name of the DHCP Relay Label.
+ type: str
+ aliases: [ name ]
+ dhcp_option:
+ description:
+ - Name of the DHCP Option Policy to be associated with the DCHP Relay Policy.
+ This policy need to be present in the same tenant as the bridge domain.
+ - The DHCP option is used to supply DHCP clients with configuration parameters
+ such as a domain, name server, subnet, and network address.
+ type: str
+ scope:
+ description:
+ - Represents the target relay servers ownership.
+ type: str
+ choices: [ infra, tenant ]
+ default: infra
+ aliases: [ owner ]
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ aliases: [ tenant_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment: cisco.aci.aci
+notes:
+- A DHCP relay label contains a C(name) for the label, the C(scope), and a DHCP option policy.
+ The scope is the C(owner) of the relay server and the DHCP option policy supplies DHCP clients
+ with configuration parameters such as domain, nameserver, and subnet router addresses.
+- The C(tenant) and C(bd) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module and M(cisco.aci.aci_bd) can be used for these.
+seealso:
+- module: cisco.aci.aci_bd
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(dhcp:Lbl).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- sig9 (@sig9org)
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Create a new DHCP Relay Label to a Bridge Domain
+ cisco.aci.aci_bd_dhcp_label:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ dhcp_label: label1
+ scope: infra
+ state: present
+
+- name: Query a DHCP Relay Label of a Bridge Domain
+ cisco.aci.aci_bd_dhcp_label:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ dhcp_label: label1
+ scope: infra
+ state: query
+
+- name: Query all DHCP Relay Labels of a Bridge Domain
+ cisco.aci.aci_bd_dhcp_label:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ state: query
+
+- name: Remove a DHCP Relay Label for a Bridge Domain
+ cisco.aci.aci_bd_dhcp_label:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ dhcp_label: label1
+ scope: infra
+ state: absent
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ bd=dict(type='str', aliases=['bd_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ dhcp_label=dict(type='str', aliases=['name']), # Not required for querying all objects
+ dhcp_option=dict(type='str'),
+ scope=dict(type='str', default='infra', choices=['infra', 'tenant'], aliases=['owner']), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['bd', 'tenant', 'dhcp_label', 'scope']],
+ ['state', 'present', ['bd', 'tenant', 'dhcp_label', 'scope']],
+ ],
+ )
+
+ tenant = module.params.get('tenant')
+ bd = module.params.get('bd')
+ description = module.params.get('description')
+ dhcp_label = module.params.get('dhcp_label')
+ dhcp_option = module.params.get('dhcp_option')
+ scope = module.params.get('scope')
+ state = module.params.get('state')
+
+ aci = ACIModule(module)
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvBD',
+ aci_rn='BD-{0}'.format(bd),
+ module_object=bd,
+ target_filter={'name': bd},
+ ),
+ subclass_2=dict(
+ aci_class='dhcpLbl',
+ aci_rn='dhcplbl-{0}'.format(dhcp_label),
+ module_object=dhcp_label,
+ target_filter={'name': dhcp_label},
+ ),
+ child_classes=['dhcpRsDhcpOptionPol'],
+ )
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='dhcpLbl',
+ class_config=dict(
+ descr=description,
+ name=dhcp_label,
+ owner=scope,
+ ),
+ child_configs=[
+ {'dhcpRsDhcpOptionPol': {'attributes': {'tnDhcpOptionPolName': dhcp_option}}},
+ ],
+ )
+
+ aci.get_diff(aci_class='dhcpLbl')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_subnet.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_subnet.py
new file mode 100644
index 00000000..ac305922
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_subnet.py
@@ -0,0 +1,467 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_bd_subnet
+short_description: Manage Subnets (fv:Subnet)
+description:
+- Manage Subnets on Cisco ACI fabrics.
+options:
+ bd:
+ description:
+ - The name of the Bridge Domain.
+ type: str
+ aliases: [ bd_name ]
+ description:
+ description:
+ - The description for the Subnet.
+ type: str
+ aliases: [ descr ]
+ enable_vip:
+ description:
+ - Determines if the Subnet should be treated as a VIP; used when the BD is extended to multiple sites.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ gateway:
+ description:
+ - The IPv4 or IPv6 gateway address for the Subnet.
+ type: str
+ aliases: [ gateway_ip ]
+ mask:
+ description:
+ - The subnet mask for the Subnet.
+ - This is the number associated with CIDR notation.
+ - For IPv4 addresses, accepted values range between C(0) and C(32).
+ - For IPv6 addresses, accepted Values range between C(0) and C(128).
+ type: int
+ aliases: [ subnet_mask ]
+ nd_prefix_policy:
+ description:
+ - The IPv6 Neighbor Discovery Prefix Policy to associate with the Subnet.
+ type: str
+ preferred:
+ description:
+ - Determines if the Subnet is preferred over all available Subnets. Only one Subnet per Address Family (IPv4/IPv6).
+ can be preferred in the Bridge Domain.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ route_profile:
+ description:
+ - The Route Profile to the associate with the Subnet.
+ type: str
+ route_profile_l3_out:
+ description:
+ - The L3 Out that contains the associated Route Profile.
+ type: str
+ scope:
+ description:
+ - Determines the scope of the Subnet.
+ - The C(private) option only allows communication with hosts in the same VRF.
+ - The C(public) option allows the Subnet to be advertised outside of the ACI Fabric, and allows communication with
+ hosts in other VRFs.
+ - The shared option limits communication to hosts in either the same VRF or the shared VRF.
+ - The value is a list of options, C(private) and C(public) are mutually exclusive, but both can be used with C(shared).
+ - The APIC defaults to C(private) when unset during creation.
+ type: list
+ elements: str
+ choices:
+ - private
+ - public
+ - shared
+ subnet_control:
+ description:
+ - Determines the Subnet's Control State.
+ - The C(querier_ip) option is used to treat the gateway_ip as an IGMP querier source IP.
+ - The C(nd_ra) option is used to treat the gateway_ip address as a Neighbor Discovery Router Advertisement Prefix.
+ - The C(no_gw) option is used to remove default gateway functionality from the gateway address.
+ - The APIC defaults to C(nd_ra) when unset during creation.
+ type: str
+ choices: [ nd_ra, no_gw, querier_ip, unspecified ]
+ subnet_name:
+ description:
+ - The name of the Subnet.
+ type: str
+ aliases: [ name ]
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ aliases: [ tenant_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(gateway) parameter is the root key used to access the Subnet (not name), so the C(gateway)
+ is required when the state is C(absent) or C(present).
+- The C(tenant) and C(bd) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module and M(cisco.aci.aci_bd) can be used for these.
+seealso:
+- module: cisco.aci.aci_bd
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:Subnet).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Create a tenant
+ cisco.aci.aci_tenant:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ state: present
+ delegate_to: localhost
+
+- name: Create a bridge domain
+ cisco.aci.aci_bd:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ state: present
+ delegate_to: localhost
+
+- name: Create a subnet
+ cisco.aci.aci_bd_subnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ gateway: 10.1.1.1
+ mask: 24
+ state: present
+ delegate_to: localhost
+
+- name: Create a subnet with options
+ cisco.aci.aci_bd_subnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ subnet_name: sql
+ gateway: 10.1.2.1
+ mask: 23
+ description: SQL Servers
+ scope: public
+ route_profile_l3_out: corp
+ route_profile: corp_route_profile
+ state: present
+ delegate_to: localhost
+
+- name: Update a subnets scope to private and shared
+ cisco.aci.aci_bd_subnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ gateway: 10.1.1.1
+ mask: 24
+ scope: [private, shared]
+ state: present
+ delegate_to: localhost
+
+- name: Get all subnets
+ cisco.aci.aci_bd_subnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+
+- name: Get all subnets of specific gateway in specified tenant
+ cisco.aci.aci_bd_subnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ gateway: 10.1.1.1
+ mask: 24
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Get specific subnet
+ cisco.aci.aci_bd_subnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ gateway: 10.1.1.1
+ mask: 24
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Delete a subnet
+ cisco.aci.aci_bd_subnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ bd: database
+ gateway: 10.1.1.1
+ mask: 24
+ state: absent
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+SUBNET_CONTROL_MAPPING = dict(
+ nd_ra='nd',
+ no_gw='no-default-gateway',
+ querier_ip='querier',
+ unspecified='',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ bd=dict(type='str', aliases=['bd_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ enable_vip=dict(type='bool'),
+ gateway=dict(type='str', aliases=['gateway_ip']), # Not required for querying all objects
+ mask=dict(type='int', aliases=['subnet_mask']), # Not required for querying all objects
+ subnet_name=dict(type='str', aliases=['name']),
+ nd_prefix_policy=dict(type='str'),
+ preferred=dict(type='bool'),
+ route_profile=dict(type='str'),
+ route_profile_l3_out=dict(type='str'),
+ scope=dict(type='list', elements='str', choices=['private', 'public', 'shared']),
+ subnet_control=dict(type='str', choices=['nd_ra', 'no_gw', 'querier_ip', 'unspecified']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_together=[['gateway', 'mask']],
+ required_if=[
+ ['state', 'present', ['bd', 'gateway', 'mask', 'tenant']],
+ ['state', 'absent', ['bd', 'gateway', 'mask', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ description = module.params.get('description')
+ enable_vip = aci.boolean(module.params.get('enable_vip'))
+ tenant = module.params.get('tenant')
+ bd = module.params.get('bd')
+ gateway = module.params.get('gateway')
+ mask = module.params.get('mask')
+ if mask is not None and mask not in range(0, 129):
+ # TODO: split checks between IPv4 and IPv6 Addresses
+ module.fail_json(msg='Valid Subnet Masks are 0 to 32 for IPv4 Addresses and 0 to 128 for IPv6 addresses')
+ if gateway is not None:
+ gateway = '{0}/{1}'.format(gateway, str(mask))
+ subnet_name = module.params.get('subnet_name')
+ nd_prefix_policy = module.params.get('nd_prefix_policy')
+ preferred = aci.boolean(module.params.get('preferred'))
+ route_profile = module.params.get('route_profile')
+ route_profile_l3_out = module.params.get('route_profile_l3_out')
+ scope = module.params.get('scope')
+ if scope is not None:
+ if 'private' in scope and 'public' in scope:
+ module.fail_json(msg="Parameter 'scope' cannot be both 'private' and 'public', got: %s" % scope)
+ else:
+ scope = ','.join(sorted(scope))
+ state = module.params.get('state')
+ subnet_control = module.params.get('subnet_control')
+ if subnet_control:
+ subnet_control = SUBNET_CONTROL_MAPPING[subnet_control]
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvBD',
+ aci_rn='BD-{0}'.format(bd),
+ module_object=bd,
+ target_filter={'name': bd},
+ ),
+ subclass_2=dict(
+ aci_class='fvSubnet',
+ aci_rn='subnet-[{0}]'.format(gateway),
+ module_object=gateway,
+ target_filter={'ip': gateway},
+ ),
+ child_classes=['fvRsBDSubnetToProfile', 'fvRsNdPfxPol'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvSubnet',
+ class_config=dict(
+ ctrl=subnet_control,
+ descr=description,
+ ip=gateway,
+ name=subnet_name,
+ preferred=preferred,
+ scope=scope,
+ virtual=enable_vip,
+ nameAlias=name_alias,
+ ),
+ child_configs=[
+ {'fvRsBDSubnetToProfile': {'attributes': {'tnL3extOutName': route_profile_l3_out, 'tnRtctrlProfileName': route_profile}}},
+ {'fvRsNdPfxPol': {'attributes': {'tnNdPfxPolName': nd_prefix_policy}}},
+ ],
+ )
+
+ aci.get_diff(aci_class='fvSubnet')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_to_l3out.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_to_l3out.py
new file mode 100644
index 00000000..c50bafad
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_bd_to_l3out.py
@@ -0,0 +1,240 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_bd_to_l3out
+short_description: Bind Bridge Domain to L3 Out (fv:RsBDToOut)
+description:
+- Bind Bridge Domain to L3 Out on Cisco ACI fabrics.
+options:
+ bd:
+ description:
+ - The name of the Bridge Domain.
+ type: str
+ aliases: [ bd_name, bridge_domain ]
+ l3out:
+ description:
+ - The name of the l3out to associate with th Bridge Domain.
+ type: str
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ aliases: [ tenant_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(bd) and C(l3out) parameters should exist before using this module.
+ The M(cisco.aci.aci_bd) and C(aci_l3out) can be used for these.
+seealso:
+- module: cisco.aci.aci_bd
+- module: cisco.aci.aci_l3out
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:RsBDToOut).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+# FIXME: Add examples
+EXAMPLES = r''' # '''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+SUBNET_CONTROL_MAPPING = dict(
+ nd_ra='nd',
+ no_gw='no-default-gateway',
+ querier_ip='querier',
+ unspecified='',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ bd=dict(type='str', aliases=['bd_name', 'bridge_domain']), # Not required for querying all objects
+ l3out=dict(type='str'), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'present', ['bd', 'l3out', 'tenant']],
+ ['state', 'absent', ['bd', 'l3out', 'tenant']],
+ ],
+ )
+
+ bd = module.params.get('bd')
+ l3out = module.params.get('l3out')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvBD',
+ aci_rn='BD-{0}'.format(bd),
+ module_object=bd,
+ target_filter={'name': bd},
+ ),
+ subclass_2=dict(
+ aci_class='fvRsBDToOut',
+ aci_rn='rsBDToOut-{0}'.format(l3out),
+ module_object=l3out,
+ target_filter={'tnL3extOutName': l3out},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvRsBDToOut',
+ class_config=dict(tnL3extOutName=l3out),
+ )
+
+ aci.get_diff(aci_class='fvRsBDToOut')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_cidr.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_cidr.py
new file mode 100644
index 00000000..8a8cbc49
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_cidr.py
@@ -0,0 +1,292 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, nkatarmal-crest <nirav.katarmal@crestdatasys.com>
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_cloud_cidr
+short_description: Manage CIDR under Cloud Context Profile (cloud:Cidr)
+description:
+- Manage Cloud CIDR on Cisco Cloud ACI.
+author:
+- Nirav (@nirav)
+- Cindy Zhao (@cizhao)
+options:
+ address:
+ description:
+ - CIDR ip and its netmask.
+ type: str
+ aliases: [ cidr ]
+ description:
+ description:
+ - Description of the Cloud CIDR.
+ type: str
+ name_alias:
+ description:
+ - An alias for the name of the current object. This relates to the nameAlias field in ACI and is used to rename object without changing the DN.
+ type: str
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ required: yes
+ cloud_context_profile:
+ description:
+ - The name of the Cloud Context Profile.
+ type: str
+ required: yes
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ absent, present, query ]
+ default: present
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- This module is only used to manage non_primary Cloud CIDR, see M(cisco.aci.aci_cloud_ctx_profile) to create the primary CIDR.
+- More information about the internal APIC class B(cloud:Cidr) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+'''
+
+EXAMPLES = r'''
+- name: Create non_primary CIDR
+ cisco.aci.aci_cloud_cidr:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ address: 10.10.0.0/16
+ cloud_context_profile: ctxProfileName
+ state: present
+ delegate_to: localhost
+
+- name: Remove non_primary CIDR
+ cisco.aci.aci_cloud_cidr:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ address: 10.10.0.0/16
+ cloud_context_profile: ctxProfileName
+ state: absent
+ delegate_to: localhost
+
+- name: Query all CIDRs under given cloud context profile
+ cisco.aci.aci_cloud_cidr:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ cloud_context_profile: ctxProfileName
+ state: query
+ delegate_to: localhost
+
+- name: Query specific CIDR under given cloud context profile
+ cisco.aci.aci_cloud_cidr:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ cloud_context_profile: ctxProfileName
+ address: 10.10.0.0/16
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ address=dict(type='str', aliases=['cidr']),
+ description=dict(type='str'),
+ name_alias=dict(type='str'),
+ tenant=dict(type='str', required=True),
+ cloud_context_profile=dict(type='str', required=True),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['address']],
+ ['state', 'present', ['address']],
+ ],
+ )
+
+ address = module.params.get('address')
+ description = module.params.get('description')
+ name_alias = module.params.get('name_alias')
+ tenant = module.params.get('tenant')
+ cloud_context_profile = module.params.get('cloud_context_profile')
+ state = module.params.get('state')
+ child_configs = []
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ target_filter='eq(fvTenant.name, "{0}")'.format(tenant),
+ module_object=tenant
+ ),
+ subclass_1=dict(
+ aci_class='cloudCtxProfile',
+ aci_rn='ctxprofile-{0}'.format(cloud_context_profile),
+ target_filter='eq(cloudCtxProfile.name, "{0}")'.format(cloud_context_profile),
+ module_object=cloud_context_profile
+ ),
+ subclass_2=dict(
+ aci_class='cloudCidr',
+ aci_rn='cidr-[{0}]'.format(address),
+ target_filter='eq(cloudCidr.addr, "{0}")'.format(address),
+ module_object=address
+ ),
+
+ child_classes=[]
+
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='cloudCidr',
+ class_config=dict(
+ addr=address,
+ descr=description,
+ nameAlias=name_alias,
+ primary='no',
+ ),
+ child_configs=child_configs
+ )
+
+ aci.get_diff(aci_class='cloudCidr')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_ctx_profile.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_ctx_profile.py
new file mode 100644
index 00000000..7fdb3b08
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_ctx_profile.py
@@ -0,0 +1,318 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, nkatarmal-crest <nirav.katarmal@crestdatasys.com>
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_cloud_ctx_profile
+short_description: Manage Cloud Context Profile (cloud:CtxProfile)
+description:
+- Manage the Cloud Context Profile objects on Cisco Cloud ACI.
+notes:
+- More information about the internal APIC class B(cloud:CtxProfile) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+author:
+- Nirav (@crestdatasys)
+- Cindy Zhao (@cizhao)
+options:
+ name:
+ description:
+ - The name of the Cloud Context Profile
+ type: str
+ aliases: [ cloud_context_profile ]
+ description:
+ description:
+ - Description of the Cloud Context Profile
+ type: str
+ name_alias:
+ description:
+ - An alias for the name of the current object. This relates to the nameAlias field in ACI and is used to rename object without changing the DN
+ type: str
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ primary_cidr:
+ description:
+ - The subnet with netmask to use as primary CIDR block for the Cloud Context Profile.
+ type: str
+ vrf:
+ description:
+ - The name of the VRF.
+ type: str
+ region:
+ description:
+ - The name of the cloud region in which to deploy the network construct.
+ type: str
+ cloud:
+ description:
+ - The cloud vendor in which the controller runs.
+ choices: [ aws, azure ]
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ absent, present, query ]
+ type: str
+ default: present
+
+extends_documentation_fragment:
+- cisco.aci.aci
+'''
+
+EXAMPLES = r'''
+- name: Add a new aci cloud ctx profile
+ cisco.aci.aci_cloud_ctx_profile:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenant_1
+ name: cloud_ctx_profile
+ vrf: VRF1
+ region: us-west-1
+ cloud: aws
+ primary_cidr: '10.0.10.1/16'
+ state: present
+ delegate_to: localhost
+
+- name: Remove an aci cloud ctx profile
+ cisco.aci.aci_cloud_ctx_profile:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenant_1
+ name: cloud_ctx_profile
+ state: absent
+ delegate_to: localhost
+
+- name: Query a specific aci cloud ctx profile
+ cisco.aci.aci_cloud_ctx_profile:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ name: ctx_profile_1
+ state: query
+ delegate_to: localhost
+
+- name: Query all aci cloud ctx profile
+ cisco.aci.aci_cloud_ctx_profile:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ description=dict(type='str',),
+ name=dict(type='str', aliases=['cloud_context_profile']),
+ name_alias=dict(type='str',),
+ tenant=dict(type='str',),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ primary_cidr=dict(type='str',),
+ # FIXME: didn't find the flow_log in UI
+ # flow_log=dict(type='str'),
+ vrf=dict(type='str'),
+ region=dict(type='str'),
+ cloud=dict(type='str', choices=['aws', 'azure'])
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['name', 'tenant']],
+ ['state', 'present', ['name', 'tenant', 'vrf', 'region', 'primary_cidr', 'cloud']],
+ ],
+ )
+
+ description = module.params.get('description')
+ name = module.params.get('name')
+ name_alias = module.params.get('name_alias')
+ tenant = module.params.get('tenant')
+ state = module.params.get('state')
+ primary_cidr = module.params.get('primary_cidr')
+ child_configs = []
+
+ vrf = module.params.get('vrf')
+ region = module.params.get('region')
+ cloud = module.params.get('cloud')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ target_filter='eq(fvTenant.name, "{0}")'.format(tenant),
+ module_object=tenant
+ ),
+ subclass_1=dict(
+ aci_class='cloudCtxProfile',
+ aci_rn='ctxprofile-{0}'.format(name),
+ target_filter='eq(cloudCtxProfile.name, "{0}")'.format(name),
+ module_object=name
+ ),
+ child_classes=['cloudRsToCtx', 'cloudRsCtxProfileToRegion', 'cloudRouterP', 'cloudCidr']
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ child_configs.append(dict(cloudRsToCtx=dict(attributes=dict(tnFvCtxName=vrf))))
+ child_configs.append(dict(
+ cloudRsCtxProfileToRegion=dict(
+ attributes=dict(
+ tDn="uni/clouddomp/provp-{0}/region-{1}".format(cloud, region)
+ )
+ )
+ ))
+ child_configs.append(dict(
+ cloudCidr=dict(
+ attributes=dict(
+ addr=primary_cidr,
+ primary="yes"
+ )
+ )
+ ))
+ aci.payload(
+ aci_class='cloudCtxProfile',
+ class_config=dict(
+ descr=description,
+ name=name,
+ name_alias=name_alias,
+ type='regular',
+ ),
+ child_configs=child_configs
+ )
+
+ aci.get_diff(aci_class='cloudCtxProfile')
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_provider.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_provider.py
new file mode 100644
index 00000000..a236d34d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_provider.py
@@ -0,0 +1,178 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_cloud_provider
+short_description: Query Cloud Provider information (cloud:ProvP)
+description:
+- Query Cloud Provider information (cloud:ProvP) on Cisco Cloud ACI.
+author:
+- Lionel Hercot (@lhercot)
+options:
+ state:
+ description:
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ query ]
+ default: query
+ type: str
+notes:
+- More information about the internal APIC class B(cloud:ProvP) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+- This module is used to query Cloud Provider information.
+
+extends_documentation_fragment:
+- cisco.aci.aci
+'''
+
+EXAMPLES = r'''
+- name: Query cloud provider information
+ cisco.aci.aci_cloud_provider:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ state=dict(type='str', default='query', choices=['query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ )
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='cloudProvP'
+ )
+ )
+
+ aci.get_existing()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_region.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_region.py
new file mode 100644
index 00000000..6ae8dad0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_region.py
@@ -0,0 +1,219 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, nkatarmal-crest <nirav.katarmal@crestdatasys.com>
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_cloud_region
+short_description: Manage Cloud Providers Region (cloud:Region)
+description:
+- Manage Cloud Providers Region on Cisco Cloud ACI.
+author:
+- Nirav (@nirav)
+- Cindy Zhao (@cizhao)
+options:
+ region:
+ description:
+ - The name of the cloud provider's region.
+ aliases: [ name ]
+ type: str
+ cloud:
+ description:
+ - The vendor of the controller
+ choices: [ aws, azure ]
+ type: str
+ required: yes
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ query ]
+ default: query
+ type: str
+notes:
+- More information about the internal APIC class B(cloud:Region) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+- This module is used to query Cloud Providers Region.
+
+extends_documentation_fragment:
+- cisco.aci.aci
+'''
+
+EXAMPLES = r'''
+- name: Query all regions
+ cisco.aci.aci_cloud_region:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ cloud: 'aws'
+ state: query
+ delegate_to: localhost
+
+- name: Query a specific region
+ cisco.aci.aci_cloud_region:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ cloud: 'aws'
+ region: eu-west-2
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ region=dict(type='str', aliases=["name"]),
+ cloud=dict(type='str', choices=['aws', 'azure'], required=True),
+ state=dict(type='str', default='query', choices=['query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ )
+
+ region = module.params.get('region')
+ cloud = module.params.get('cloud')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='cloudProvP',
+ aci_rn='clouddomp/provp-{0}'.format(cloud),
+ target_filter='eq(cloudProvP.vendor, "{0}")'.format(cloud),
+ module_object=cloud
+ ),
+ subclass_1=dict(
+ aci_class='cloudRegion',
+ aci_rn='region-{0}'.format(region),
+ target_filter='eq(cloudRegion.name, "{0}")'.format(region),
+ module_object=region
+ ),
+ child_classes=[]
+ )
+
+ aci.get_existing()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py
new file mode 100644
index 00000000..4d17d80b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_subnet.py
@@ -0,0 +1,330 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, nkatarmal-crest <nirav.katarmal@crestdatasys.com>
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_cloud_subnet
+short_description: Manage Cloud Subnet (cloud:Subnet)
+description:
+- Manage Cloud Subnet on Cisco Cloud ACI.
+notes:
+- More information about the internal APIC class B(cloud:Subnet) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+author:
+- Nirav (@nirav)
+- Cindy Zhao (@cizhao)
+options:
+ name:
+ description:
+ - The name of the Cloud Subnet.
+ type: str
+ description:
+ description:
+ - Description of the Cloud Subnet.
+ type: str
+ address:
+ description:
+ - Ip address of the Cloud Subnet.
+ type: str
+ aliases: [subnet]
+ name_alias:
+ description:
+ - An alias for the name of the current object. This relates to the nameAlias field in ACI and is used to rename object without changing the DN.
+ type: str
+ tenant:
+ description:
+ - The name of tenant.
+ type: str
+ required: yes
+ cloud_context_profile:
+ description:
+ - The name of cloud context profile.
+ type: str
+ required: yes
+ cidr:
+ description:
+ - Address of cloud cidr.
+ type: str
+ required: yes
+ availability_zone:
+ description:
+ - The cloud zone which is attached to the given cloud context profile.
+ - Only used when it is an aws cloud apic.
+ type: str
+ vnet_gateway:
+ description:
+ - Determine if a vNet Gateway Router will be deployed or not.
+ - Only used when it is an azure cloud apic.
+ type: bool
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ absent, present, query ]
+ default: present
+ type: str
+
+extends_documentation_fragment:
+- cisco.aci.aci
+'''
+
+EXAMPLES = r'''
+- name: Create aci cloud subnet
+ cisco.aci.aci_cloud_subnet:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ tenant: anstest
+ cloud_context_profile: aws_cloudCtxProfile
+ cidr: '10.10.0.0/16'
+ availability_zone: us-west-1a
+ address: 10.10.0.1
+ delegate_to: localhost
+
+- name: Query a specific subnet
+ cisco.aci.aci_cloud_subnet:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ tenant: anstest
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.10.0.0/16'
+ address: 10.10.0.1
+ state: query
+ delegate_to: localhost
+
+- name: Query all subnets
+ cisco.aci.aci_cloud_subnet:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ tenant: anstest
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.10.0.0/16'
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ name=dict(type='str', aliases=['subnet']),
+ description=dict(type='str'),
+ address=dict(type='str'),
+ name_alias=dict(type='str'),
+ vnet_gateway=dict(type='bool', default=False),
+ tenant=dict(type='str', required=True),
+ cloud_context_profile=dict(type='str', required=True),
+ cidr=dict(type='str', required=True),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ availability_zone=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['address']],
+ ['state', 'present', ['address']],
+ ],
+ )
+
+ name = module.params.get('name')
+ description = module.params.get('description')
+ address = module.params.get('address')
+ name_alias = module.params.get('name_alias')
+ vnet_gateway = module.params.get('vnet_gateway')
+ tenant = module.params.get('tenant')
+ cloud_context_profile = module.params.get('cloud_context_profile')
+ cidr = module.params.get('cidr')
+ state = module.params.get('state')
+ availability_zone = module.params.get('availability_zone')
+ child_configs = []
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ target_filter='eq(fvTenant.name, "{0}")'.format(tenant),
+ module_object=tenant
+ ),
+ subclass_1=dict(
+ aci_class='cloudCtxProfile',
+ aci_rn='ctxprofile-{0}'.format(cloud_context_profile),
+ target_filter='eq(cloudCtxProfile.name, "{0}")'.format(cloud_context_profile),
+ module_object=cloud_context_profile
+ ),
+ subclass_2=dict(
+ aci_class='cloudCidr',
+ aci_rn='cidr-[{0}]'.format(cidr),
+ target_filter='eq(cloudCidr.addr, "{0}")'.format(cidr),
+ module_object=cidr
+ ),
+ subclass_3=dict(
+ aci_class='cloudSubnet',
+ aci_rn='subnet-[{0}]'.format(address),
+ target_filter='eq(cloudSubnet.ip, "{0}")'.format(address),
+ module_object=address
+ ),
+ child_classes=['cloudRsZoneAttach']
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ # in aws cloud apic
+ if availability_zone:
+ region = availability_zone[:-1]
+ tDn = 'uni/clouddomp/provp-aws/region-{0}/zone-{1}'.format(region, availability_zone)
+ child_configs.append({'cloudRsZoneAttach': {'attributes': {'tDn': tDn}}})
+ # in azure cloud apic
+ if vnet_gateway:
+ usage = 'gateway'
+ else:
+ usage = 'user'
+
+ aci.payload(
+ aci_class='cloudSubnet',
+ class_config=dict(
+ name=name,
+ descr=description,
+ ip=address,
+ nameAlias=name_alias,
+ scope='private',
+ usage=usage,
+ ),
+ child_configs=child_configs
+ )
+
+ aci.get_diff(aci_class='cloudSubnet')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_vpn_gateway.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_vpn_gateway.py
new file mode 100644
index 00000000..9b286dc8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_vpn_gateway.py
@@ -0,0 +1,253 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_cloud_vpn_gateway
+short_description: Manage cloudRouterP in Cloud Context Profile (cloud:cloudRouterP)
+description:
+- Manage cloudRouterP objects on Cisco Cloud ACI.
+notes:
+- More information about the internal APIC class B(cloud:cloudRouterP) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+author:
+- Cindy Zhao (@cizhao)
+options:
+ tenant:
+ description:
+ - The name of tenant.
+ type: str
+ required: yes
+ cloud_context_profile:
+ description:
+ - The name of cloud context profile.
+ type: str
+ required: yes
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ absent, present, query ]
+ type: str
+ default: query
+
+extends_documentation_fragment:
+- cisco.aci.aci
+'''
+
+EXAMPLES = r'''
+- name: Enable VpnGateway
+ cisco.aci.aci_cloud_vpn_gateway:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: present
+ delegate_to: localhost
+
+- name: Disable VpnGateway
+ cisco.aci.aci_cloud_vpn_gateway:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ delegate_to: localhost
+
+- name: Query VpnGateway
+ cisco.aci.aci_cloud_vpn_gateway:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', required=True),
+ cloud_context_profile=dict(type='str', required=True),
+ state=dict(type='str', default='query', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ )
+
+ tenant = module.params.get('tenant')
+ cloud_context_profile = module.params.get('cloud_context_profile')
+ state = module.params.get('state')
+ child_configs = []
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ target_filter='eq(fvTenant.name, "{0}")'.format(tenant),
+ module_object=tenant
+ ),
+ subclass_1=dict(
+ aci_class='cloudCtxProfile',
+ aci_rn='ctxprofile-{0}'.format(cloud_context_profile),
+ target_filter='eq(cloudCtxProfile.name, "{0}")'.format(cloud_context_profile),
+ module_object=cloud_context_profile
+ ),
+ subclass_2=dict(
+ aci_class='cloudRouterP',
+ aci_rn="routerp-default",
+ target_filter='eq(cloudRouterP.name, "default")',
+ module_object="default"
+ ),
+ child_classes=['cloudRsToVpnGwPol', 'cloudRsToHostRouterPol', 'cloudIntNetworkP']
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ child_configs.append(dict(
+ cloudIntNetworkP=dict(
+ attributes=dict(
+ name="default"
+ )
+ )
+ ))
+ aci.payload(
+ aci_class='cloudRouterP',
+ class_config=dict(
+ name="default"
+ ),
+ child_configs=child_configs
+ )
+
+ aci.get_diff(aci_class='cloudRouterP')
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_zone.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_zone.py
new file mode 100644
index 00000000..be85f18e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_cloud_zone.py
@@ -0,0 +1,233 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, nkatarmal-crest <nirav.katarmal@crestdatasys.com>
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_cloud_zone
+short_description: Manage Cloud Availability Zone (cloud:Zone)
+description:
+- Manage Cloud Availability Zone on Cisco Cloud ACI.
+notes:
+- More information about the internal APIC class B(cloud:Zone) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+- This module is used to query Cloud Availability Zone.
+author:
+- Nirav (@nirav)
+- Cindy Zhao (@cizhao)
+options:
+ name:
+ description:
+ - object name
+ aliases: [ zone ]
+ type: str
+ cloud:
+ description:
+ - The cloud provider.
+ choices: [ aws, azure ]
+ type: str
+ required: yes
+ region:
+ description:
+ - The name of the cloud provider's region.
+ type: str
+ required: yes
+ state:
+ description:
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ query ]
+ default: query
+ type: str
+
+extends_documentation_fragment:
+- cisco.aci.aci
+'''
+
+EXAMPLES = r'''
+- name: Query all zones in a region
+ cisco.aci.aci_cloud_zone:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ cloud: 'aws'
+ region: regionName
+ state: query
+ delegate_to: localhost
+
+- name: Query a specific zone
+ cisco.aci.aci_cloud_zone:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ cloud: 'aws'
+ region: regionName
+ zone: zoneName
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ name=dict(type='str', aliases=['zone']),
+ cloud=dict(type='str', choices=['aws', 'azure'], required=True),
+ region=dict(type='str', required=True),
+ state=dict(type='str', default='query', choices=['query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ )
+
+ name = module.params.get('name')
+ cloud = module.params.get('cloud')
+ region = module.params.get('region')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='cloudProvP',
+ aci_rn='clouddomp/provp-{0}'.format(cloud),
+ target_filter='eq(cloudProvP.vendor, "{0}")'.format(cloud),
+ module_object=cloud
+ ),
+ subclass_1=dict(
+ aci_class='cloudRegion',
+ aci_rn='region-{0}'.format(region),
+ target_filter='eq(cloudRegion.name, "{0}")'.format(region),
+ module_object=region
+ ),
+ subclass_2=dict(
+ aci_class='cloudZone',
+ aci_rn='zone-{0}'.format(name),
+ target_filter='eq(cloudZone.name, "{0}")'.format(name),
+ module_object=name
+ ),
+ child_classes=[]
+ )
+
+ aci.get_existing()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_rollback.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_rollback.py
new file mode 100644
index 00000000..fb8ffc19
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_rollback.py
@@ -0,0 +1,321 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_config_rollback
+short_description: Provides rollback and rollback preview functionality (config:ImportP)
+description:
+- Provides rollback and rollback preview functionality for Cisco ACI fabrics.
+- Config Rollbacks are done using snapshots C(aci_snapshot) with the configImportP class.
+options:
+ compare_export_policy:
+ description:
+ - The export policy that the C(compare_snapshot) is associated to.
+ type: str
+ compare_snapshot:
+ description:
+ - The name of the snapshot to compare with C(snapshot).
+ type: str
+ description:
+ description:
+ - The description for the Import Policy.
+ type: str
+ aliases: [ descr ]
+ export_policy:
+ description:
+ - The export policy that the C(snapshot) is associated to.
+ type: str
+ fail_on_decrypt:
+ description:
+ - Determines if the APIC should fail the rollback if unable to decrypt secured data.
+ - The APIC defaults to C(yes) when unset.
+ type: bool
+ import_mode:
+ description:
+ - Determines how the import should be handled by the APIC.
+ - The APIC defaults to C(atomic) when unset.
+ type: str
+ choices: [ atomic, best-effort ]
+ import_policy:
+ description:
+ - The name of the Import Policy to use for config rollback.
+ type: str
+ import_type:
+ description:
+ - Determines how the current and snapshot configuration should be compared for replacement.
+ - The APIC defaults to C(replace) when unset.
+ type: str
+ choices: [ merge, replace ]
+ snapshot:
+ description:
+ - The name of the snapshot to rollback to, or the base snapshot to use for comparison.
+ - The C(aci_snapshot) module can be used to query the list of available snapshots.
+ type: str
+ required: yes
+ state:
+ description:
+ - Use C(preview) for previewing the diff between two snapshots.
+ - Use C(rollback) for reverting the configuration to a previous snapshot.
+ type: str
+ choices: [ preview, rollback ]
+ default: rollback
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_config_snapshot
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(config:ImportP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+---
+- name: Create a Snapshot
+ cisco.aci.aci_config_snapshot:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ export_policy: config_backup
+ state: present
+ delegate_to: localhost
+
+- name: Query Existing Snapshots
+ cisco.aci.aci_config_snapshot:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ export_policy: config_backup
+ state: query
+ delegate_to: localhost
+
+- name: Compare Snapshot Files
+ cisco.aci.aci_config_rollback:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ export_policy: config_backup
+ snapshot: run-2017-08-28T06-24-01
+ compare_export_policy: config_backup
+ compare_snapshot: run-2017-08-27T23-43-56
+ state: preview
+ delegate_to: localhost
+
+- name: Rollback Configuration
+ cisco.aci.aci_config_rollback:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ import_policy: rollback_config
+ export_policy: config_backup
+ snapshot: run-2017-08-28T06-24-01
+ state: rollback
+ delegate_to: localhost
+
+- name: Rollback Configuration
+ cisco.aci.aci_config_rollback:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ import_policy: rollback_config
+ export_policy: config_backup
+ snapshot: run-2017-08-28T06-24-01
+ description: Rollback 8-27 changes
+ import_mode: atomic
+ import_type: replace
+ fail_on_decrypt: yes
+ state: rollback
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+preview:
+ description: A preview between two snapshots
+ returned: when state is preview
+ type: str
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils.urls import fetch_url
+
+# Optional, only used for rollback preview
+try:
+ import lxml.etree
+ from xmljson import cobra
+ XML_TO_JSON = True
+except ImportError:
+ XML_TO_JSON = False
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ compare_export_policy=dict(type='str'),
+ compare_snapshot=dict(type='str'),
+ description=dict(type='str', aliases=['descr']),
+ export_policy=dict(type='str'),
+ fail_on_decrypt=dict(type='bool'),
+ import_mode=dict(type='str', choices=['atomic', 'best-effort']),
+ import_policy=dict(type='str'),
+ import_type=dict(type='str', choices=['merge', 'replace']),
+ snapshot=dict(type='str', required=True),
+ state=dict(type='str', default='rollback', choices=['preview', 'rollback']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=False,
+ required_if=[
+ ['state', 'preview', ['compare_export_policy', 'compare_snapshot']],
+ ['state', 'rollback', ['import_policy']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ description = module.params.get('description')
+ export_policy = module.params.get('export_policy')
+ fail_on_decrypt = aci.boolean(module.params.get('fail_on_decrypt'))
+ import_mode = module.params.get('import_mode')
+ import_policy = module.params.get('import_policy')
+ import_type = module.params.get('import_type')
+ snapshot = module.params.get('snapshot')
+ state = module.params.get('state')
+
+ if state == 'rollback':
+ if snapshot.startswith('run-'):
+ snapshot = snapshot.replace('run-', '', 1)
+
+ if not snapshot.endswith('.tar.gz'):
+ snapshot += '.tar.gz'
+
+ filename = 'ce2_{0}-{1}'.format(export_policy, snapshot)
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='configImportP',
+ aci_rn='fabric/configimp-{0}'.format(import_policy),
+ module_object=import_policy,
+ target_filter={'name': import_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ aci.payload(
+ aci_class='configImportP',
+ class_config=dict(
+ adminSt='triggered',
+ descr=description,
+ failOnDecryptErrors=fail_on_decrypt,
+ fileName=filename,
+ importMode=import_mode,
+ importType=import_type,
+ name=import_policy,
+ snapshot='yes',
+ ),
+ )
+
+ aci.get_diff(aci_class='configImportP')
+
+ aci.post_config()
+
+ elif state == 'preview':
+ aci.url = '%(protocol)s://%(host)s/mqapi2/snapshots.diff.xml' % module.params
+ aci.filter_string = (
+ '?s1dn=uni/backupst/snapshots-[uni/fabric/configexp-%(export_policy)s]/snapshot-%(snapshot)s&'
+ 's2dn=uni/backupst/snapshots-[uni/fabric/configexp-%(compare_export_policy)s]/snapshot-%(compare_snapshot)s'
+ ) % module.params
+
+ # Generate rollback comparison
+ get_preview(aci)
+
+ aci.exit_json()
+
+
+def get_preview(aci):
+ '''
+ This function is used to generate a preview between two snapshots and add the parsed results to the aci module return data.
+ '''
+ uri = aci.url + aci.filter_string
+ resp, info = fetch_url(aci.module, uri, headers=aci.headers, method='GET', timeout=aci.module.params.get('timeout'),
+ use_proxy=aci.module.params.get('use_proxy'))
+ aci.method = 'GET'
+ aci.response = info.get('msg')
+ aci.status = info.get('status')
+
+ # Handle APIC response
+ if info.get('status') == 200:
+ xml_to_json(aci, resp.read())
+ else:
+ aci.result['raw'] = resp.read()
+ aci.fail_json(msg="Request failed: %(code)s %(text)s (see 'raw' output)" % aci.error)
+
+
+def xml_to_json(aci, response_data):
+ '''
+ This function is used to convert preview XML data into JSON.
+ '''
+ if XML_TO_JSON:
+ xml = lxml.etree.fromstring(to_bytes(response_data))
+ xmldata = cobra.data(xml)
+ aci.result['preview'] = xmldata
+ else:
+ aci.result['preview'] = response_data
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py
new file mode 100644
index 00000000..8f71ca01
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_config_snapshot.py
@@ -0,0 +1,337 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_config_snapshot
+short_description: Manage Config Snapshots (config:Snapshot, config:ExportP)
+description:
+- Manage Config Snapshots on Cisco ACI fabrics.
+- Creating new Snapshots is done using the configExportP class.
+- Removing Snapshots is done using the configSnapshot class.
+options:
+ description:
+ description:
+ - The description for the Config Export Policy.
+ type: str
+ aliases: [ descr ]
+ export_policy:
+ description:
+ - The name of the Export Policy to use for Config Snapshots.
+ type: str
+ aliases: [ name ]
+ format:
+ description:
+ - Sets the config backup to be formatted in JSON or XML.
+ - The APIC defaults to C(json) when unset.
+ type: str
+ choices: [ json, xml ]
+ include_secure:
+ description:
+ - Determines if secure information should be included in the backup.
+ - The APIC defaults to C(yes) when unset.
+ type: bool
+ max_count:
+ description:
+ - Determines how many snapshots can exist for the Export Policy before the APIC starts to rollover.
+ - Accepted values range between C(1) and C(10).
+ - The APIC defaults to C(3) when unset.
+ type: int
+ snapshot:
+ description:
+ - The name of the snapshot to delete.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The APIC does not provide a mechanism for naming the snapshots.
+- 'Snapshot files use the following naming structure: ce_<config export policy name>-<yyyy>-<mm>-<dd>T<hh>:<mm>:<ss>.<mss>+<hh>:<mm>.'
+- 'Snapshot objects use the following naming structure: run-<yyyy>-<mm>-<dd>T<hh>-<mm>-<ss>.'
+seealso:
+- module: cisco.aci.aci_config_rollback
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(config:Snapshot) and B(config:ExportP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Create a Snapshot
+ cisco.aci.aci_config_snapshot:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: present
+ export_policy: config_backup
+ max_count: 10
+ description: Backups taken before new configs are applied.
+ delegate_to: localhost
+
+- name: Query all Snapshots
+ cisco.aci.aci_config_snapshot:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query Snapshots associated with a particular Export Policy
+ cisco.aci.aci_config_snapshot:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ export_policy: config_backup
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Delete a Snapshot
+ cisco.aci.aci_config_snapshot:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ export_policy: config_backup
+ snapshot: run-2017-08-24T17-20-05
+ state: absent
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ description=dict(type='str', aliases=['descr']),
+ export_policy=dict(type='str', aliases=['name']), # Not required for querying all objects
+ format=dict(type='str', choices=['json', 'xml']),
+ include_secure=dict(type='bool'),
+ max_count=dict(type='int'),
+ snapshot=dict(type='str'),
+ state=dict(type='str', choices=['absent', 'present', 'query'], default='present'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=False,
+ required_if=[
+ ['state', 'absent', ['export_policy', 'snapshot']],
+ ['state', 'present', ['export_policy']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ description = module.params.get('description')
+ export_policy = module.params.get('export_policy')
+ file_format = module.params.get('format')
+ include_secure = aci.boolean(module.params.get('include_secure'))
+ max_count = module.params.get('max_count')
+ if max_count is not None:
+ if max_count in range(1, 11):
+ max_count = str(max_count)
+ else:
+ module.fail_json(msg="Parameter 'max_count' must be a number between 1 and 10")
+ snapshot = module.params.get('snapshot')
+ if snapshot is not None and not snapshot.startswith('run-'):
+ snapshot = 'run-' + snapshot
+ state = module.params.get('state')
+
+ if state == 'present':
+ aci.construct_url(
+ root_class=dict(
+ aci_class='configExportP',
+ aci_rn='fabric/configexp-{0}'.format(export_policy),
+ module_object=export_policy,
+ target_filter={'name': export_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ aci.payload(
+ aci_class='configExportP',
+ class_config=dict(
+ adminSt='triggered',
+ descr=description,
+ format=file_format,
+ includeSecureFields=include_secure,
+ maxSnapshotCount=max_count,
+ name=export_policy,
+ snapshot='yes',
+ ),
+ )
+
+ aci.get_diff('configExportP')
+
+ # Create a new Snapshot
+ aci.post_config()
+
+ else:
+ # Prefix the proper url to export_policy
+ if export_policy is not None:
+ export_policy = 'uni/fabric/configexp-{0}'.format(export_policy)
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='configSnapshotCont',
+ aci_rn='backupst/snapshots-[{0}]'.format(export_policy),
+ module_object=export_policy,
+ target_filter={'name': export_policy},
+ ),
+ subclass_1=dict(
+ aci_class='configSnapshot',
+ aci_rn='snapshot-{0}'.format(snapshot),
+ module_object=snapshot,
+ target_filter={'name': snapshot},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'absent':
+ # Build POST request to used to remove Snapshot
+ aci.payload(
+ aci_class='configSnapshot',
+ class_config=dict(
+ name=snapshot,
+ retire="yes",
+ ),
+ )
+
+ if aci.existing:
+ aci.get_diff('configSnapshot')
+
+ # Mark Snapshot for Deletion
+ aci.post_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract.py
new file mode 100644
index 00000000..36f6e00f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract.py
@@ -0,0 +1,312 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_contract
+short_description: Manage contract resources (vz:BrCP)
+description:
+- Manage Contract resources on Cisco ACI fabrics.
+options:
+ contract:
+ description:
+ - The name of the contract.
+ type: str
+ aliases: [ contract_name, name ]
+ description:
+ description:
+ - Description for the contract.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ scope:
+ description:
+ - The scope of a service contract.
+ - The APIC defaults to C(context) when unset during creation.
+ type: str
+ choices: [ application-profile, context, global, tenant ]
+ priority:
+ description:
+ - The desired QoS class to be used.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ level1, level2, level3, unspecified ]
+ dscp:
+ description:
+ - The target Differentiated Service (DSCP) value.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ AF11, AF12, AF13, AF21, AF22, AF23, AF31, AF32, AF33, AF41, AF42, AF43, CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, EF, VA, unspecified ]
+ aliases: [ target ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- This module does not manage Contract Subjects, see M(cisco.aci.aci_contract_subject) to do this.
+ Contract Subjects can still be removed using this module.
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_contract_subject
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(vz:BrCP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add a new contract
+ cisco.aci.aci_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ description: Communication between web-servers and database
+ scope: application-profile
+ state: present
+ delegate_to: localhost
+
+- name: Remove an existing contract
+ cisco.aci.aci_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ state: absent
+ delegate_to: localhost
+
+- name: Query a specific contract
+ cisco.aci.aci_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all contracts
+ cisco.aci.aci_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ contract=dict(type='str', aliases=['contract_name', 'name']), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ scope=dict(type='str', choices=['application-profile', 'context', 'global', 'tenant']),
+ priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']), # No default provided on purpose
+ dscp=dict(type='str',
+ choices=['AF11', 'AF12', 'AF13', 'AF21', 'AF22', 'AF23', 'AF31', 'AF32', 'AF33', 'AF41', 'AF42', 'AF43',
+ 'CS0', 'CS1', 'CS2', 'CS3', 'CS4', 'CS5', 'CS6', 'CS7', 'EF', 'VA', 'unspecified'],
+ aliases=['target']), # No default provided on purpose
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['contract', 'tenant']],
+ ['state', 'present', ['contract', 'tenant']],
+ ],
+ )
+
+ contract = module.params.get('contract')
+ description = module.params.get('description')
+ scope = module.params.get('scope')
+ priority = module.params.get('priority')
+ dscp = module.params.get('dscp')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='vzBrCP',
+ aci_rn='brc-{0}'.format(contract),
+ module_object=contract,
+ target_filter={'name': contract},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='vzBrCP',
+ class_config=dict(
+ name=contract,
+ descr=description,
+ scope=scope,
+ prio=priority,
+ targetDscp=dscp,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='vzBrCP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject.py
new file mode 100644
index 00000000..24fc8ed0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject.py
@@ -0,0 +1,358 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_contract_subject
+short_description: Manage initial Contract Subjects (vz:Subj)
+description:
+- Manage initial Contract Subjects on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ subject:
+ description:
+ - The contract subject name.
+ type: str
+ aliases: [ contract_subject, name, subject_name ]
+ contract:
+ description:
+ - The name of the Contract.
+ type: str
+ aliases: [ contract_name ]
+ reverse_filter:
+ description:
+ - Determines if the APIC should reverse the src and dst ports to allow the
+ return traffic back, since ACI is stateless filter.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ priority:
+ description:
+ - The QoS class.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ level1, level2, level3, unspecified ]
+ dscp:
+ description:
+ - The target DSCP.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ AF11, AF12, AF13, AF21, AF22, AF23, AF31, AF32, AF33, AF41, AF42, AF43,
+ CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, EF, VA, unspecified ]
+ aliases: [ target ]
+ description:
+ description:
+ - Description for the contract subject.
+ type: str
+ aliases: [ descr ]
+ consumer_match:
+ description:
+ - The match criteria across consumers.
+ - The APIC defaults to C(at_least_one) when unset during creation.
+ type: str
+ choices: [ all, at_least_one, at_most_one, none ]
+ provider_match:
+ description:
+ - The match criteria across providers.
+ - The APIC defaults to C(at_least_one) when unset during creation.
+ type: str
+ choices: [ all, at_least_one, at_most_one, none ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(contract) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_contract) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_contract
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(vz:Subj).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Swetha Chunduri (@schunduri)
+'''
+
+EXAMPLES = r'''
+- name: Add a new contract subject
+ cisco.aci.aci_contract_subject:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ subject: default
+ description: test
+ reverse_filter: yes
+ priority: level1
+ dscp: unspecified
+ state: present
+ register: query_result
+
+- name: Remove a contract subject
+ cisco.aci.aci_contract_subject:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ subject: default
+ state: absent
+ delegate_to: localhost
+
+- name: Query a contract subject
+ cisco.aci.aci_contract_subject:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ subject: default
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all contract subjects
+ cisco.aci.aci_contract_subject:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+MATCH_MAPPING = dict(
+ all='All',
+ at_least_one='AtleastOne',
+ at_most_one='AtmostOne',
+ none='None',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ contract=dict(type='str', aliases=['contract_name']), # Not required for querying all objects
+ subject=dict(type='str', aliases=['contract_subject', 'name', 'subject_name']), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ priority=dict(type='str', choices=['unspecified', 'level1', 'level2', 'level3']),
+ reverse_filter=dict(type='bool'),
+ dscp=dict(type='str', aliases=['target'],
+ choices=['AF11', 'AF12', 'AF13', 'AF21', 'AF22', 'AF23', 'AF31', 'AF32', 'AF33', 'AF41', 'AF42', 'AF43',
+ 'CS0', 'CS1', 'CS2', 'CS3', 'CS4', 'CS5', 'CS6', 'CS7', 'EF', 'VA', 'unspecified']),
+ description=dict(type='str', aliases=['descr']),
+ consumer_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
+ provider_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['contract', 'subject', 'tenant']],
+ ['state', 'present', ['contract', 'subject', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ subject = module.params.get('subject')
+ priority = module.params.get('priority')
+ reverse_filter = aci.boolean(module.params.get('reverse_filter'))
+ contract = module.params.get('contract')
+ dscp = module.params.get('dscp')
+ description = module.params.get('description')
+ consumer_match = module.params.get('consumer_match')
+ if consumer_match is not None:
+ consumer_match = MATCH_MAPPING.get(consumer_match)
+ provider_match = module.params.get('provider_match')
+ if provider_match is not None:
+ provider_match = MATCH_MAPPING.get(provider_match)
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='vzBrCP',
+ aci_rn='brc-{0}'.format(contract),
+ module_object=contract,
+ target_filter={'name': contract},
+ ),
+ subclass_2=dict(
+ aci_class='vzSubj',
+ aci_rn='subj-{0}'.format(subject),
+ module_object=subject,
+ target_filter={'name': subject},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='vzSubj',
+ class_config=dict(
+ name=subject,
+ prio=priority,
+ revFltPorts=reverse_filter,
+ targetDscp=dscp,
+ consMatchT=consumer_match,
+ provMatchT=provider_match,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='vzSubj')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_filter.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_filter.py
new file mode 100644
index 00000000..5698295a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_contract_subject_to_filter.py
@@ -0,0 +1,319 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_contract_subject_to_filter
+short_description: Bind Contract Subjects to Filters (vz:RsSubjFiltAtt)
+description:
+- Bind Contract Subjects to Filters on Cisco ACI fabrics.
+options:
+ contract:
+ description:
+ - The name of the contract.
+ type: str
+ aliases: [ contract_name ]
+ filter:
+ description:
+ - The name of the Filter to bind to the Subject.
+ type: str
+ aliases: [ filter_name ]
+ log:
+ description:
+ - Determines if the binding should be set to log.
+ - The APIC defaults to C(none) when unset during creation.
+ type: str
+ choices: [ log, none ]
+ aliases: [ directive ]
+ subject:
+ description:
+ - The name of the Contract Subject.
+ type: str
+ aliases: [ contract_subject, subject_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant), C(contract), C(subject), and C(filter_name) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant), M(cisco.aci.aci_contract), M(cisco.aci.aci_contract_subject), and M(cisco.aci.aci_filter) modules can be used for these.
+seealso:
+- module: cisco.aci.aci_contract_subject
+- module: cisco.aci.aci_filter
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(vz:RsSubjFiltAtt).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Add a new contract subject to filer binding
+ cisco.aci.aci_contract_subject_to_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ subject: test
+ filter: '{{ filter }}'
+ log: '{{ log }}'
+ state: present
+ delegate_to: localhost
+
+- name: Remove an existing contract subject to filter binding
+ cisco.aci.aci_contract_subject_to_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ subject: test
+ filter: '{{ filter }}'
+ log: '{{ log }}'
+ state: present
+ delegate_to: localhost
+
+- name: Query a specific contract subject to filter binding
+ cisco.aci.aci_contract_subject_to_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ subject: test
+ filter: '{{ filter }}'
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all contract subject to filter bindings
+ cisco.aci.aci_contract_subject_to_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ contract: web_to_db
+ subject: test
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ contract=dict(type='str', aliases=['contract_name']), # Not required for querying all objects
+ filter=dict(type='str', aliases=['filter_name']), # Not required for querying all objects
+ subject=dict(type='str', aliases=['contract_subject', 'subject_name']), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ log=dict(type='str', choices=['log', 'none'], aliases=['directive']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['contract', 'filter', 'subject', 'tenant']],
+ ['state', 'present', ['contract', 'filter', 'subject', 'tenant']],
+ ],
+ )
+
+ contract = module.params.get('contract')
+ filter_name = module.params.get('filter')
+ log = module.params.get('log')
+ subject = module.params.get('subject')
+ tenant = module.params.get('tenant')
+ state = module.params.get('state')
+
+ # Add subject_filter key to modul.params for building the URL
+ module.params['subject_filter'] = filter_name
+
+ # Convert log to empty string if none, as that is what API expects. An empty string is not a good option to present the user.
+ if log == 'none':
+ log = ''
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='vzBrCP',
+ aci_rn='brc-{0}'.format(contract),
+ module_object=contract,
+ target_filter={'name': contract},
+ ),
+ subclass_2=dict(
+ aci_class='vzSubj',
+ aci_rn='subj-{0}'.format(subject),
+ module_object=subject,
+ target_filter={'name': subject},
+ ),
+ subclass_3=dict(
+ aci_class='vzRsSubjFiltAtt',
+ aci_rn='rssubjFiltAtt-{0}'.format(filter_name),
+ module_object=filter_name,
+ target_filter={'tnVzFilterName': filter_name},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='vzRsSubjFiltAtt',
+ class_config=dict(
+ tnVzFilterName=filter_name,
+ directives=log,
+ ),
+ )
+
+ aci.get_diff(aci_class='vzRsSubjFiltAtt')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ # Remove subject_filter used to build URL from module.params
+ module.params.pop('subject_filter')
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain.py
new file mode 100644
index 00000000..82ee9a32
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain.py
@@ -0,0 +1,395 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_domain
+short_description: Manage physical, virtual, bridged, routed or FC domain profiles (phys:DomP, vmm:DomP, l2ext:DomP, l3ext:DomP, fc:DomP)
+description:
+- Manage physical, virtual, bridged, routed or FC domain profiles on Cisco ACI fabrics.
+options:
+ domain:
+ description:
+ - Name of the physical, virtual, bridged routed or FC domain profile.
+ type: str
+ aliases: [ domain_name, domain_profile, name ]
+ domain_type:
+ description:
+ - The type of domain profile.
+ - 'C(fc): The FC domain profile is a policy pertaining to single FC Management domain'
+ - 'C(l2dom): The external bridged domain profile is a policy for managing L2 bridged infrastructure bridged outside the fabric.'
+ - 'C(l3dom): The external routed domain profile is a policy for managing L3 routed infrastructure outside the fabric.'
+ - 'C(phys): The physical domain profile stores the physical resources and encap resources that should be used for EPGs associated with this domain.'
+ - 'C(vmm): The VMM domain profile is a policy for grouping VM controllers with similar networking policy requirements.'
+ type: str
+ required: yes
+ choices: [ fc, l2dom, l3dom, phys, vmm ]
+ aliases: [ type ]
+ dscp:
+ description:
+ - The target Differentiated Service (DSCP) value.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ AF11, AF12, AF13, AF21, AF22, AF23, AF31, AF32, AF33, AF41, AF42, AF43, CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, EF, VA, unspecified ]
+ aliases: [ target ]
+ encap_mode:
+ description:
+ - The layer 2 encapsulation protocol to use with the virtual switch.
+ type: str
+ choices: [ unknown, vlan, vxlan ]
+ multicast_address:
+ description:
+ - The multicast IP address to use for the virtual switch.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ vm_provider:
+ description:
+ - The VM platform for VMM Domains.
+ - Support for Kubernetes was added in ACI v3.0.
+ - Support for CloudFoundry, OpenShift and Red Hat was added in ACI v3.1.
+ type: str
+ choices: [ cloudfoundry, kubernetes, microsoft, openshift, openstack, redhat, vmware ]
+ vswitch:
+ description:
+ - The virtual switch to use for vmm domains.
+ - The APIC defaults to C(default) when unset during creation.
+ type: str
+ choices: [ avs, default, dvs, unknown ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_aep_to_domain
+- module: cisco.aci.aci_domain_to_encap_pool
+- module: cisco.aci.aci_domain_to_vlan_pool
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(phys:DomP),
+ B(vmm:DomP), B(l2ext:DomP), B(l3ext:DomP) and B(fc:DomP)
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add a new physical domain
+ cisco.aci.aci_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ state: present
+
+- name: Remove a physical domain
+ cisco.aci.aci_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ state: absent
+
+- name: Add a new VMM domain
+ cisco.aci.aci_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: hyperv_dom
+ domain_type: vmm
+ vm_provider: microsoft
+ state: present
+ delegate_to: localhost
+
+- name: Remove a VMM domain
+ cisco.aci.aci_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: hyperv_dom
+ domain_type: vmm
+ vm_provider: microsoft
+ state: absent
+ delegate_to: localhost
+
+- name: Query a specific physical domain
+ cisco.aci.aci_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all domains
+ cisco.aci.aci_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain_type: phys
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+VM_PROVIDER_MAPPING = dict(
+ cloudfoundry='CloudFoundry',
+ kubernetes='Kubernetes',
+ microsoft='Microsoft',
+ openshift='OpenShift',
+ openstack='OpenStack',
+ redhat='Redhat',
+ vmware='VMware',
+)
+
+VSWITCH_MAPPING = dict(
+ avs='n1kv',
+ default='default',
+ dvs='default',
+ unknown='unknown',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ domain_type=dict(type='str', required=True, choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm'], aliases=['type']),
+ domain=dict(type='str', aliases=['domain_name', 'domain_profile', 'name']), # Not required for querying all objects
+ dscp=dict(type='str',
+ choices=['AF11', 'AF12', 'AF13', 'AF21', 'AF22', 'AF23', 'AF31', 'AF32', 'AF33', 'AF41', 'AF42', 'AF43',
+ 'CS0', 'CS1', 'CS2', 'CS3', 'CS4', 'CS5', 'CS6', 'CS7', 'EF', 'VA', 'unspecified'],
+ aliases=['target']),
+ encap_mode=dict(type='str', choices=['unknown', 'vlan', 'vxlan']),
+ multicast_address=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']),
+ vswitch=dict(type='str', choices=['avs', 'default', 'dvs', 'unknown']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['domain_type', 'vmm', ['vm_provider']],
+ ['state', 'absent', ['domain', 'domain_type']],
+ ['state', 'present', ['domain', 'domain_type']],
+ ],
+ )
+
+ dscp = module.params.get('dscp')
+ domain = module.params.get('domain')
+ domain_type = module.params.get('domain_type')
+ encap_mode = module.params.get('encap_mode')
+ multicast_address = module.params.get('multicast_address')
+ vm_provider = module.params.get('vm_provider')
+ vswitch = module.params.get('vswitch')
+ if vswitch is not None:
+ vswitch = VSWITCH_MAPPING.get(vswitch)
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ if domain_type != 'vmm':
+ if vm_provider is not None:
+ module.fail_json(msg="Domain type '{0}' cannot have parameter 'vm_provider'".format(domain_type))
+ if encap_mode is not None:
+ module.fail_json(msg="Domain type '{0}' cannot have parameter 'encap_mode'".format(domain_type))
+ if multicast_address is not None:
+ module.fail_json(msg="Domain type '{0}' cannot have parameter 'multicast_address'".format(domain_type))
+ if vswitch is not None:
+ module.fail_json(msg="Domain type '{0}' cannot have parameter 'vswitch'".format(domain_type))
+
+ if dscp is not None and domain_type not in ['l2dom', 'l3dom']:
+ module.fail_json(msg="DSCP values can only be assigned to 'l2ext and 'l3ext' domains")
+
+ # Compile the full domain for URL building
+ if domain_type == 'fc':
+ domain_class = 'fcDomP'
+ domain_mo = 'uni/fc-{0}'.format(domain)
+ domain_rn = 'fc-{0}'.format(domain)
+ elif domain_type == 'l2dom':
+ domain_class = 'l2extDomP'
+ domain_mo = 'uni/l2dom-{0}'.format(domain)
+ domain_rn = 'l2dom-{0}'.format(domain)
+ elif domain_type == 'l3dom':
+ domain_class = 'l3extDomP'
+ domain_mo = 'uni/l3dom-{0}'.format(domain)
+ domain_rn = 'l3dom-{0}'.format(domain)
+ elif domain_type == 'phys':
+ domain_class = 'physDomP'
+ domain_mo = 'uni/phys-{0}'.format(domain)
+ domain_rn = 'phys-{0}'.format(domain)
+ elif domain_type == 'vmm':
+ domain_class = 'vmmDomP'
+ domain_mo = 'uni/vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING.get(vm_provider), domain)
+ domain_rn = 'vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING.get(vm_provider), domain)
+
+ # Ensure that querying all objects works when only domain_type is provided
+ if domain is None:
+ domain_mo = None
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class=domain_class,
+ aci_rn=domain_rn,
+ module_object=domain_mo,
+ target_filter={'name': domain},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=domain_class,
+ class_config=dict(
+ encapMode=encap_mode,
+ mcastAddr=multicast_address,
+ mode=vswitch,
+ name=domain,
+ targetDscp=dscp,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class=domain_class)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_encap_pool.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_encap_pool.py
new file mode 100644
index 00000000..a571cfb3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_encap_pool.py
@@ -0,0 +1,378 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Dag Wieers <dag@wieers.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_domain_to_encap_pool
+short_description: Bind Domain to Encap Pools (infra:RsVlanNs)
+description:
+- Bind Domain to Encap Pools on Cisco ACI fabrics.
+notes:
+- The C(domain) and C(encap_pool) parameters should exist before using this module.
+ The M(cisco.aci.aci_domain) and M(cisco.aci.aci_encap_pool) can be used for these.
+options:
+ domain:
+ description:
+ - Name of the domain being associated with the Encap Pool.
+ type: str
+ aliases: [ domain_name, domain_profile ]
+ domain_type:
+ description:
+ - Determines if the Domain is physical (phys) or virtual (vmm).
+ type: str
+ required: yes
+ choices: [ fc, l2dom, l3dom, phys, vmm ]
+ pool:
+ description:
+ - The name of the pool.
+ type: str
+ aliases: [ pool_name ]
+ pool_allocation_mode:
+ description:
+ - The method used for allocating encaps to resources.
+ - Only vlan and vsan support allocation modes.
+ type: str
+ choices: [ dynamic, static]
+ aliases: [ allocation_mode, mode ]
+ pool_type:
+ description:
+ - The encap type of C(pool).
+ type: str
+ required: yes
+ choices: [ vlan, vsan, vxlan ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ vm_provider:
+ description:
+ - The VM platform for VMM Domains.
+ - Support for Kubernetes was added in ACI v3.0.
+ - Support for CloudFoundry, OpenShift and Red Hat was added in ACI v3.1.
+ type: str
+ choices: [ cloudfoundry, kubernetes, microsoft, openshift, openstack, redhat, vmware ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_domain
+- module: cisco.aci.aci_encap_pool
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(infra:RsVlanNs).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add domain to VLAN pool binding
+ cisco.aci.aci_domain_to_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ state: present
+ delegate_to: localhost
+
+- name: Remove domain to VLAN pool binding
+ cisco.aci.aci_domain_to_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ state: absent
+ delegate_to: localhost
+
+- name: Query our domain to VLAN pool binding
+ cisco.aci.aci_domain_to_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ pool: test_pool
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all domain to VLAN pool bindings
+ cisco.aci.aci_domain_to_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain_type: phys
+ pool_type: vlan
+ pool_allocation_mode: dynamic
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+VM_PROVIDER_MAPPING = dict(
+ cloudfoundry='CloudFoundry',
+ kubernetes='Kubernetes',
+ microsoft='Microsoft',
+ openshift='OpenShift',
+ openstack='OpenStack',
+ redhat='Redhat',
+ vmware='VMware',
+)
+
+POOL_MAPPING = dict(
+ vlan=dict(
+ aci_mo='uni/infra/vlanns-{0}',
+ child_class='infraRsVlanNs',
+ ),
+ vxlan=dict(
+ aci_mo='uni/infra/vxlanns-{0}',
+ child_class='vmmRsVxlanNs',
+ ),
+ vsan=dict(
+ aci_mo='uni/infra/vsanns-{0}',
+ child_class='fcRsVsanNs',
+ ),
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ domain_type=dict(type='str', required=True, choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm']),
+ pool_type=dict(type='str', required=True, choices=['vlan', 'vsan', 'vxlan']),
+ domain=dict(type='str', aliases=['domain_name', 'domain_profile']), # Not required for querying all objects
+ pool=dict(type='str', aliases=['pool_name']), # Not required for querying all objects
+ pool_allocation_mode=dict(type='str', aliases=['allocation_mode', 'mode'], choices=['dynamic', 'static']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['domain_type', 'vmm', ['vm_provider']],
+ ['state', 'absent', ['domain', 'domain_type', 'pool', 'pool_type']],
+ ['state', 'present', ['domain', 'domain_type', 'pool', 'pool_type']],
+ ],
+ )
+
+ domain = module.params.get('domain')
+ domain_type = module.params.get('domain_type')
+ pool = module.params.get('pool')
+ pool_allocation_mode = module.params.get('pool_allocation_mode')
+ pool_type = module.params.get('pool_type')
+ vm_provider = module.params.get('vm_provider')
+ state = module.params.get('state')
+
+ # Report when vm_provider is set when type is not virtual
+ if domain_type != 'vmm' and vm_provider is not None:
+ module.fail_json(msg="Domain type '{0}' cannot have a 'vm_provider'".format(domain_type))
+
+ # ACI Pool URL requires the allocation mode for vlan and vsan pools (ex: uni/infra/vlanns-[poolname]-static)
+ pool_name = pool
+ if pool_type != 'vxlan' and pool is not None:
+ if pool_allocation_mode is not None:
+ pool_name = '[{0}]-{1}'.format(pool, pool_allocation_mode)
+ else:
+ module.fail_json(msg="ACI requires the 'pool_allocation_mode' for 'pool_type' of 'vlan' and 'vsan' when 'pool' is provided")
+
+ # Vxlan pools do not support allocation modes
+ if pool_type == 'vxlan' and pool_allocation_mode is not None:
+ module.fail_json(msg='vxlan pools do not support setting the allocation_mode; please remove this parameter from the task')
+
+ # Compile the full domain for URL building
+ if domain_type == 'fc':
+ domain_class = 'fcDomP'
+ domain_mo = 'uni/fc-{0}'.format(domain)
+ domain_rn = 'fc-{0}'.format(domain)
+ elif domain_type == 'l2dom':
+ domain_class = 'l2extDomP'
+ domain_mo = 'uni/l2dom-{0}'.format(domain)
+ domain_rn = 'l2dom-{0}'.format(domain)
+ elif domain_type == 'l3dom':
+ domain_class = 'l3extDomP'
+ domain_mo = 'uni/l3dom-{0}'.format(domain)
+ domain_rn = 'l3dom-{0}'.format(domain)
+ elif domain_type == 'phys':
+ domain_class = 'physDomP'
+ domain_mo = 'uni/phys-{0}'.format(domain)
+ domain_rn = 'phys-{0}'.format(domain)
+ elif domain_type == 'vmm':
+ domain_class = 'vmmDomP'
+ domain_mo = 'uni/vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
+ domain_rn = 'vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
+
+ # Ensure that querying all objects works when only domain_type is provided
+ if domain is None:
+ domain_mo = None
+
+ pool_mo = POOL_MAPPING[pool_type]['aci_mo'].format(pool_name)
+ child_class = POOL_MAPPING[pool_type]['child_class']
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class=domain_class,
+ aci_rn=domain_rn,
+ module_object=domain_mo,
+ target_filter={'name': domain},
+ ),
+ child_classes=[child_class],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ # Filter out module params with null values
+ aci.payload(
+ aci_class=domain_class,
+ class_config=dict(name=domain),
+ child_configs=[
+ {child_class: {'attributes': {'tDn': pool_mo}}},
+ ]
+ )
+
+ # Generate config diff which will be used as POST request body
+ aci.get_diff(aci_class=domain_class)
+
+ # Submit changes if module not in check_mode and the proposed is different than existing
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_vlan_pool.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_vlan_pool.py
new file mode 100644
index 00000000..0e213128
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_domain_to_vlan_pool.py
@@ -0,0 +1,366 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Dag Wieers <dag@wieers.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_domain_to_vlan_pool
+short_description: Bind Domain to VLAN Pools (infra:RsVlanNs)
+description:
+- Bind Domain to VLAN Pools on Cisco ACI fabrics.
+options:
+ domain:
+ description:
+ - Name of the domain being associated with the VLAN Pool.
+ type: str
+ aliases: [ domain_name, domain_profile ]
+ domain_type:
+ description:
+ - Determines if the Domain is physical (phys) or virtual (vmm).
+ type: str
+ required: yes
+ choices: [ fc, l2dom, l3dom, phys, vmm ]
+ pool:
+ description:
+ - The name of the pool.
+ type: str
+ aliases: [ pool_name, vlan_pool ]
+ pool_allocation_mode:
+ description:
+ - The method used for allocating VLANs to resources.
+ type: str
+ required: yes
+ choices: [ dynamic, static]
+ aliases: [ allocation_mode, mode ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ vm_provider:
+ description:
+ - The VM platform for VMM Domains.
+ - Support for Kubernetes was added in ACI v3.0.
+ - Support for CloudFoundry, OpenShift and Red Hat was added in ACI v3.1.
+ type: str
+ choices: [ cloudfoundry, kubernetes, microsoft, openshift, openstack, redhat, vmware ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(domain) and C(vlan_pool) parameters should exist before using this module.
+ The M(cisco.aci.aci_domain) and M(cisco.aci.aci_vlan_pool) can be used for these.
+seealso:
+- module: cisco.aci.aci_domain
+- module: cisco.aci.aci_vlan_pool
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(infra:RsVlanNs).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Bind a VMM domain to VLAN pool
+ cisco.aci.aci_domain_to_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: vmw_dom
+ domain_type: vmm
+ pool: vmw_pool
+ pool_allocation_mode: dynamic
+ vm_provider: vmware
+ state: present
+ delegate_to: localhost
+
+- name: Remove a VMM domain to VLAN pool binding
+ cisco.aci.aci_domain_to_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: vmw_dom
+ domain_type: vmm
+ pool: vmw_pool
+ pool_allocation_mode: dynamic
+ vm_provider: vmware
+ state: absent
+ delegate_to: localhost
+
+- name: Bind a physical domain to VLAN pool
+ cisco.aci.aci_domain_to_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ pool: phys_pool
+ pool_allocation_mode: static
+ state: present
+ delegate_to: localhost
+
+- name: Bind a physical domain to VLAN pool
+ cisco.aci.aci_domain_to_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ pool: phys_pool
+ pool_allocation_mode: static
+ state: absent
+ delegate_to: localhost
+
+- name: Query an domain to VLAN pool binding
+ cisco.aci.aci_domain_to_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: phys_dom
+ domain_type: phys
+ pool: phys_pool
+ pool_allocation_mode: static
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all domain to VLAN pool bindings
+ cisco.aci.aci_domain_to_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain_type: phys
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+VM_PROVIDER_MAPPING = dict(
+ cloudfoundry='CloudFoundry',
+ kubernetes='Kubernetes',
+ microsoft='Microsoft',
+ openshift='OpenShift',
+ openstack='OpenStack',
+ redhat='Redhat',
+ vmware='VMware',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ domain_type=dict(type='str', required=True, choices=['fc', 'l2dom', 'l3dom', 'phys', 'vmm']),
+ domain=dict(type='str', aliases=['domain_name', 'domain_profile']), # Not required for querying all objects
+ pool=dict(type='str', aliases=['pool_name', 'vlan_pool']), # Not required for querying all objects
+ pool_allocation_mode=dict(type='str', required=True, aliases=['allocation_mode', 'mode'], choices=['dynamic', 'static']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['domain_type', 'vmm', ['vm_provider']],
+ ['state', 'absent', ['domain', 'domain_type', 'pool']],
+ ['state', 'present', ['domain', 'domain_type', 'pool']],
+ ],
+ )
+
+ domain = module.params.get('domain')
+ domain_type = module.params.get('domain_type')
+ pool = module.params.get('pool')
+ pool_allocation_mode = module.params.get('pool_allocation_mode')
+ vm_provider = module.params.get('vm_provider')
+ state = module.params.get('state')
+
+ # Report when vm_provider is set when type is not virtual
+ if domain_type != 'vmm' and vm_provider is not None:
+ module.fail_json(msg="Domain type '{0}' cannot have a 'vm_provider'".format(domain_type))
+
+ # ACI Pool URL requires the allocation mode for vlan and vsan pools (ex: uni/infra/vlanns-[poolname]-static)
+ pool_name = pool
+ if pool is not None:
+ pool_name = '[{0}]-{1}'.format(pool, pool_allocation_mode)
+
+ # Compile the full domain for URL building
+ if domain_type == 'fc':
+ domain_class = 'fcDomP'
+ domain_mo = 'uni/fc-{0}'.format(domain)
+ domain_rn = 'fc-{0}'.format(domain)
+ elif domain_type == 'l2dom':
+ domain_class = 'l2extDomP'
+ domain_mo = 'uni/l2dom-{0}'.format(domain)
+ domain_rn = 'l2dom-{0}'.format(domain)
+ elif domain_type == 'l3dom':
+ domain_class = 'l3extDomP'
+ domain_mo = 'uni/l3dom-{0}'.format(domain)
+ domain_rn = 'l3dom-{0}'.format(domain)
+ elif domain_type == 'phys':
+ domain_class = 'physDomP'
+ domain_mo = 'uni/phys-{0}'.format(domain)
+ domain_rn = 'phys-{0}'.format(domain)
+ elif domain_type == 'vmm':
+ domain_class = 'vmmDomP'
+ domain_mo = 'uni/vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
+ domain_rn = 'vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
+
+ # Ensure that querying all objects works when only domain_type is provided
+ if domain is None:
+ domain_mo = None
+
+ aci_mo = 'uni/infra/vlanns-{0}'.format(pool_name)
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class=domain_class,
+ aci_rn=domain_rn,
+ module_object=domain_mo,
+ target_filter={'name': domain},
+ ),
+ child_classes=['infraRsVlanNs'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=domain_class,
+ class_config=dict(name=domain),
+ child_configs=[
+ {'infraRsVlanNs': {'attributes': {'tDn': aci_mo}}},
+ ]
+ )
+
+ aci.get_diff(aci_class=domain_class)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py
new file mode 100644
index 00000000..f35b9342
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool.py
@@ -0,0 +1,316 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_encap_pool
+short_description: Manage encap pools (fvns:VlanInstP, fvns:VxlanInstP, fvns:VsanInstP)
+description:
+- Manage vlan, vxlan, and vsan pools on Cisco ACI fabrics.
+options:
+ description:
+ description:
+ - Description for the C(pool).
+ type: str
+ aliases: [ descr ]
+ pool:
+ description:
+ - The name of the pool.
+ type: str
+ aliases: [ name, pool_name ]
+ pool_allocation_mode:
+ description:
+ - The method used for allocating encaps to resources.
+ - Only vlan and vsan support allocation modes.
+ type: str
+ choices: [ dynamic, static ]
+ aliases: [ allocation_mode, mode ]
+ pool_type:
+ description:
+ - The encap type of C(pool).
+ type: str
+ required: yes
+ aliases: [ type ]
+ choices: [ vlan, vsan, vxlan ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_encap_pool_range
+- module: cisco.aci.aci_vlan_pool
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(fvns:VlanInstP),
+ B(fvns:VxlanInstP) and B(fvns:VsanInstP)
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Add a new vlan pool
+ cisco.aci.aci_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_type: vlan
+ description: Production VLANs
+ state: present
+ delegate_to: localhost
+
+- name: Remove a vlan pool
+ cisco.aci.aci_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_type: vlan
+ state: absent
+ delegate_to: localhost
+
+- name: Query a vlan pool
+ cisco.aci.aci_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_type: vlan
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all vlan pools
+ cisco.aci.aci_encap_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool_type: vlan
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+ACI_POOL_MAPPING = dict(
+ vlan=dict(
+ aci_class='fvnsVlanInstP',
+ aci_mo='infra/vlanns-',
+ ),
+ vxlan=dict(
+ aci_class='fvnsVxlanInstP',
+ aci_mo='infra/vxlanns-',
+ ),
+ vsan=dict(
+ aci_class='fvnsVsanInstP',
+ aci_mo='infra/vsanns-',
+ ),
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ pool_type=dict(type='str', required=True, aliases=['type'], choices=['vlan', 'vsan', 'vxlan']),
+ description=dict(type='str', aliases=['descr']),
+ pool=dict(type='str', aliases=['name', 'pool_name']), # Not required for querying all objects
+ pool_allocation_mode=dict(type='str', aliases=['allocation_mode', 'mode'], choices=['dynamic', 'static']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['pool']],
+ ['state', 'present', ['pool']],
+ ],
+ )
+
+ description = module.params.get('description')
+ pool = module.params.get('pool')
+ pool_type = module.params.get('pool_type')
+ pool_allocation_mode = module.params.get('pool_allocation_mode')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci_class = ACI_POOL_MAPPING[pool_type]['aci_class']
+ aci_mo = ACI_POOL_MAPPING[pool_type]['aci_mo']
+ pool_name = pool
+
+ # ACI Pool URL requires the pool_allocation mode for vlan and vsan pools (ex: uni/infra/vlanns-[poolname]-static)
+ if pool_type != 'vxlan' and pool is not None:
+ if pool_allocation_mode is not None:
+ pool_name = '[{0}]-{1}'.format(pool, pool_allocation_mode)
+ else:
+ module.fail_json(msg="ACI requires parameter 'pool_allocation_mode' for 'pool_type' of 'vlan' and 'vsan' when parameter 'pool' is provided")
+
+ # Vxlan pools do not support pool allocation modes
+ if pool_type == 'vxlan' and pool_allocation_mode is not None:
+ module.fail_json(msg="vxlan pools do not support setting the 'pool_allocation_mode'; please remove this parameter from the task")
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class=aci_class,
+ aci_rn='{0}{1}'.format(aci_mo, pool_name),
+ module_object=pool,
+ target_filter={'name': pool},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ # Filter out module parameters with null values
+ aci.payload(
+ aci_class=aci_class,
+ class_config=dict(
+ allocMode=pool_allocation_mode,
+ descr=description,
+ name=pool,
+ nameAlias=name_alias,
+ )
+ )
+
+ # Generate config diff which will be used as POST request body
+ aci.get_diff(aci_class=aci_class)
+
+ # Submit changes if module not in check_mode and the proposed is different than existing
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py
new file mode 100644
index 00000000..8e24fadc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_encap_pool_range.py
@@ -0,0 +1,449 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_encap_pool_range
+short_description: Manage encap ranges assigned to pools (fvns:EncapBlk, fvns:VsanEncapBlk)
+description:
+- Manage vlan, vxlan, and vsan ranges that are assigned to pools on Cisco ACI fabrics.
+options:
+ allocation_mode:
+ description:
+ - The method used for allocating encaps to resources.
+ - Only vlan and vsan support allocation modes.
+ type: str
+ choices: [ dynamic, inherit, static]
+ aliases: [ mode ]
+ description:
+ description:
+ - Description for the pool range.
+ type: str
+ aliases: [ descr ]
+ pool:
+ description:
+ - The name of the pool that the range should be assigned to.
+ type: str
+ aliases: [ pool_name ]
+ pool_allocation_mode:
+ description:
+ - The method used for allocating encaps to resources.
+ - Only vlan and vsan support allocation modes.
+ type: str
+ choices: [ dynamic, static]
+ aliases: [ pool_mode ]
+ pool_type:
+ description:
+ - The encap type of C(pool).
+ type: str
+ required: yes
+ aliases: [ type ]
+ choices: [ vlan, vxlan, vsan]
+ range_end:
+ description:
+ - The end of encap range.
+ type: int
+ aliases: [ end ]
+ range_name:
+ description:
+ - The name to give to the encap range.
+ type: str
+ aliases: [ name, range ]
+ range_start:
+ description:
+ - The start of the encap range.
+ type: int
+ aliases: [ start ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(pool) must exist in order to add or delete a range.
+seealso:
+- module: cisco.aci.aci_encap_pool
+- module: cisco.aci.aci_vlan_pool_encap_block
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(fvns:EncapBlk) and B(fvns:VsanEncapBlk).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Add a new VLAN pool range
+ cisco.aci.aci_encap_pool_range:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_type: vlan
+ pool_allocation_mode: static
+ range_name: anstest
+ range_start: 20
+ range_end: 40
+ allocation_mode: inherit
+ state: present
+ delegate_to: localhost
+
+- name: Remove a VLAN pool range
+ cisco.aci.aci_encap_pool_range:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_type: vlan
+ pool_allocation_mode: static
+ range_name: anstest
+ range_start: 20
+ range_end: 40
+ state: absent
+ delegate_to: localhost
+
+- name: Query a VLAN range
+ cisco.aci.aci_encap_pool_range:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_type: vlan
+ pool_allocation_mode: static
+ range_name: anstest
+ range_start: 20
+ range_end: 50
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a VLAN pool for ranges by range_name
+ cisco.aci.aci_encap_pool_range:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool_type: vlan
+ range_name: anstest
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a VLAN pool for ranges by range_start
+ cisco.aci.aci_encap_pool_range:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool_type: vlan
+ range_start: 20
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a VLAN pool for ranges by range_start and range_end
+ cisco.aci.aci_encap_pool_range:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool_type: vlan
+ range_start: 20
+ range_end: 40
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all VLAN pool ranges
+ cisco.aci.aci_encap_pool_range:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool_type: vlan
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+ACI_POOL_MAPPING = dict(
+ vlan=dict(
+ aci_class='fvnsVlanInstP',
+ aci_mo='infra/vlanns-',
+ ),
+ vxlan=dict(
+ aci_class='fvnsVxlanInstP',
+ aci_mo='infra/vxlanns-',
+ ),
+ vsan=dict(
+ aci_class='fvnsVsanInstP',
+ aci_mo='infra/vsanns-',
+ ),
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ pool_type=dict(type='str', required=True, aliases=['type'], choices=['vlan', 'vxlan', 'vsan']),
+ allocation_mode=dict(type='str', aliases=['mode'], choices=['dynamic', 'inherit', 'static']),
+ description=dict(type='str', aliases=['descr']),
+ pool=dict(type='str', aliases=['pool_name']), # Not required for querying all objects
+ pool_allocation_mode=dict(type='str', aliases=['pool_mode'], choices=['dynamic', 'static']),
+ range_end=dict(type='int', aliases=['end']), # Not required for querying all objects
+ range_name=dict(type='str', aliases=["name", "range"]), # Not required for querying all objects
+ range_start=dict(type='int', aliases=["start"]), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['pool', 'range_end', 'range_name', 'range_start']],
+ ['state', 'present', ['pool', 'range_end', 'range_name', 'range_start']],
+ ],
+ )
+
+ allocation_mode = module.params.get('allocation_mode')
+ description = module.params.get('description')
+ pool = module.params.get('pool')
+ pool_allocation_mode = module.params.get('pool_allocation_mode')
+ pool_type = module.params.get('pool_type')
+ range_end = module.params.get('range_end')
+ range_name = module.params.get('range_name')
+ range_start = module.params.get('range_start')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ if range_end is not None:
+ encap_end = '{0}-{1}'.format(pool_type, range_end)
+ else:
+ encap_end = None
+
+ if range_start is not None:
+ encap_start = '{0}-{1}'.format(pool_type, range_start)
+ else:
+ encap_start = None
+
+ ACI_RANGE_MAPPING = dict(
+ vlan=dict(
+ aci_class='fvnsEncapBlk',
+ aci_mo='from-[{0}]-to-[{1}]'.format(encap_start, encap_end),
+ ),
+ vxlan=dict(
+ aci_class='fvnsEncapBlk',
+ aci_mo='from-[{0}]-to-[{1}]'.format(encap_start, encap_end),
+ ),
+ vsan=dict(
+ aci_class='fvnsVsanEncapBlk',
+ aci_mo='vsanfrom-[{0}]-to-[{1}]'.format(encap_start, encap_end),
+ ),
+ )
+
+ # Collect proper class and mo information based on pool_type
+ aci_range_class = ACI_RANGE_MAPPING[pool_type]["aci_class"]
+ aci_range_mo = ACI_RANGE_MAPPING[pool_type]["aci_mo"]
+ aci_pool_class = ACI_POOL_MAPPING[pool_type]["aci_class"]
+ aci_pool_mo = ACI_POOL_MAPPING[pool_type]["aci_mo"]
+ pool_name = pool
+
+ # Validate range_end and range_start are valid for its respective encap type
+ for encap_id in range_end, range_start:
+ if encap_id is not None:
+ if pool_type == 'vlan':
+ if not 1 <= encap_id <= 4094:
+ module.fail_json(msg='vlan pools must have "range_start" and "range_end" values between 1 and 4094')
+ elif pool_type == 'vxlan':
+ if not 5000 <= encap_id <= 16777215:
+ module.fail_json(msg='vxlan pools must have "range_start" and "range_end" values between 5000 and 16777215')
+ elif pool_type == 'vsan':
+ if not 1 <= encap_id <= 4093:
+ module.fail_json(msg='vsan pools must have "range_start" and "range_end" values between 1 and 4093')
+
+ if range_end is not None and range_start is not None:
+ # Validate range_start is less than range_end
+ if range_start > range_end:
+ module.fail_json(msg='The "range_start" must be less than or equal to the "range_end"')
+
+ elif range_end is None and range_start is None:
+ if range_name is None:
+ # Reset range managed object to None for aci util to properly handle query
+ aci_range_mo = None
+
+ # Vxlan does not support setting the allocation mode
+ if pool_type == 'vxlan' and allocation_mode is not None:
+ module.fail_json(msg='vxlan pools do not support setting the "allocation_mode"; please omit this parameter for vxlan pools')
+
+ # ACI Pool URL requires the allocation mode for vlan and vsan pools (ex: uni/infra/vlanns-[poolname]-static)
+ if pool_type != 'vxlan' and pool is not None:
+ if pool_allocation_mode is not None:
+ pool_name = '[{0}]-{1}'.format(pool, pool_allocation_mode)
+ else:
+ module.fail_json(msg='ACI requires the "pool_allocation_mode" for "pool_type" of "vlan" and "vsan" when the "pool" is provided')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class=aci_pool_class,
+ aci_rn='{0}{1}'.format(aci_pool_mo, pool_name),
+ module_object=pool,
+ target_filter={'name': pool},
+ ),
+ subclass_1=dict(
+ aci_class=aci_range_class,
+ aci_rn='{0}'.format(aci_range_mo),
+ module_object=aci_range_mo,
+ target_filter={'from': encap_start, 'to': encap_end, 'name': range_name},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=aci_range_class,
+ class_config={
+ "allocMode": allocation_mode,
+ "descr": description,
+ "from": encap_start,
+ "name": range_name,
+ "to": encap_end,
+ "nameAlias": name_alias,
+ },
+ )
+
+ aci.get_diff(aci_class=aci_range_class)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg.py
new file mode 100644
index 00000000..986206a8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg.py
@@ -0,0 +1,398 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_epg
+short_description: Manage End Point Groups (EPG) objects (fv:AEPg)
+description:
+- Manage End Point Groups (EPG) on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ ap:
+ description:
+ - Name of an existing application network profile, that will contain the EPGs.
+ type: str
+ aliases: [ app_profile, app_profile_name ]
+ epg:
+ description:
+ - Name of the end point group.
+ type: str
+ aliases: [ epg_name, name ]
+ bd:
+ description:
+ - Name of the bridge domain being associated with the EPG.
+ type: str
+ aliases: [ bd_name, bridge_domain ]
+ priority:
+ description:
+ - The QoS class.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ level1, level2, level3, unspecified ]
+ intra_epg_isolation:
+ description:
+ - The Intra EPG Isolation.
+ - The APIC defaults to C(unenforced) when unset during creation.
+ type: str
+ choices: [ enforced, unenforced ]
+ description:
+ description:
+ - Description for the EPG.
+ type: str
+ aliases: [ descr ]
+ fwd_control:
+ description:
+ - The forwarding control used by the EPG.
+ - The APIC defaults to C(none) when unset during creation.
+ type: str
+ choices: [ none, proxy-arp ]
+ preferred_group:
+ description:
+ - Whether ot not the EPG is part of the Preferred Group and can communicate without contracts.
+ - This is very convenient for migration scenarios, or when ACI is used for network automation but not for policy.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ monitoring_policy:
+ description:
+ - The name of the monitoring policy.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(app_profile) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_ap) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_ap
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:AEPg).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Swetha Chunduri (@schunduri)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Add a new EPG
+ cisco.aci.aci_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ap: intranet
+ epg: web_epg
+ description: Web Intranet EPG
+ bd: prod_bd
+ monitoring_policy: default
+ preferred_group: yes
+ state: present
+ delegate_to: localhost
+
+- aci_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ap: ticketing
+ epg: "{{ item.epg }}"
+ description: Ticketing EPG
+ bd: "{{ item.bd }}"
+ priority: unspecified
+ intra_epg_isolation: unenforced
+ state: present
+ delegate_to: localhost
+ with_items:
+ - epg: web
+ bd: web_bd
+ - epg: database
+ bd: database_bd
+
+- name: Remove an EPG
+ cisco.aci.aci_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ validate_certs: no
+ tenant: production
+ app_profile: intranet
+ epg: web_epg
+ monitoring_policy: default
+ state: absent
+ delegate_to: localhost
+
+- name: Query an EPG
+ cisco.aci.aci_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ap: ticketing
+ epg: web_epg
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all EPGs
+ cisco.aci.aci_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all EPGs with a Specific Name
+ cisco.aci.aci_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ validate_certs: no
+ epg: web_epg
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all EPGs of an App Profile
+ cisco.aci.aci_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ validate_certs: no
+ ap: ticketing
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ epg=dict(type='str', aliases=['epg_name', 'name']), # Not required for querying all objects
+ bd=dict(type='str', aliases=['bd_name', 'bridge_domain']),
+ ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),
+ intra_epg_isolation=dict(choices=['enforced', 'unenforced']),
+ fwd_control=dict(type='str', choices=['none', 'proxy-arp']),
+ preferred_group=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ monitoring_policy=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['ap', 'epg', 'tenant']],
+ ['state', 'present', ['ap', 'epg', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ epg = module.params.get('epg')
+ bd = module.params.get('bd')
+ description = module.params.get('description')
+ priority = module.params.get('priority')
+ intra_epg_isolation = module.params.get('intra_epg_isolation')
+ fwd_control = module.params.get('fwd_control')
+ preferred_group = aci.boolean(module.params.get('preferred_group'), 'include', 'exclude')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ ap = module.params.get('ap')
+ name_alias = module.params.get('name_alias')
+ monitoring_policy = module.params.get('monitoring_policy')
+
+ child_configs = [
+ dict(fvRsBd=dict(attributes=dict(tnFvBDName=bd))),
+ dict(fvRsAEPgMonPol=dict(attributes=dict(tnMonEPGPolName=monitoring_policy)))
+ ]
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvAp',
+ aci_rn='ap-{0}'.format(ap),
+ module_object=ap,
+ target_filter={'name': ap},
+ ),
+ subclass_2=dict(
+ aci_class='fvAEPg',
+ aci_rn='epg-{0}'.format(epg),
+ module_object=epg,
+ target_filter={'name': epg},
+ ),
+ child_classes=['fvRsBd', 'fvRsAEPgMonPol'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvAEPg',
+ class_config=dict(
+ name=epg,
+ descr=description,
+ prio=priority,
+ pcEnfPref=intra_epg_isolation,
+ fwdCtrl=fwd_control,
+ prefGrMemb=preferred_group,
+ nameAlias=name_alias,
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='fvAEPg')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_monitoring_policy.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_monitoring_policy.py
new file mode 100644
index 00000000..aaef8e37
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_monitoring_policy.py
@@ -0,0 +1,246 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_epg_monitoring_policy
+short_description: Manage monitoring policies (mon:EPGPol)
+description:
+- Manage monitoring policies on Cisco ACI fabrics.
+options:
+ monitoring_policy:
+ description:
+ - The name of the monitoring policy.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - Description for the monitoring policy.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(mon:EPGPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- cisco.aci.aci_epg_monitoring_policy:
+ host: '{{ hostname }}'
+ username: '{{ username }}'
+ password: '{{ password }}'
+ monitoring_policy: '{{ monitoring_policy }}'
+ description: '{{ description }}'
+ tenant: '{{ tenant }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ monitoring_policy=dict(type='str', aliases=['name']), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['monitoring_policy', 'tenant']],
+ ['state', 'present', ['monitoring_policy', 'tenant']],
+ ],
+ )
+
+ monitoring_policy = module.params.get('monitoring_policy')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='monEPGPol',
+ aci_rn='monepg-{0}'.format(monitoring_policy),
+ module_object=monitoring_policy,
+ target_filter={'name': monitoring_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='monEPGPol',
+ class_config=dict(
+ name=monitoring_policy,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='monEPGPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py
new file mode 100644
index 00000000..45be2dd1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract.py
@@ -0,0 +1,351 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_epg_to_contract
+short_description: Bind EPGs to Contracts (fv:RsCons, fv:RsProv)
+description:
+- Bind EPGs to Contracts on Cisco ACI fabrics.
+notes:
+- The C(tenant), C(app_profile), C(EPG), and C(Contract) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant), M(cisco.aci.aci_ap), M(cisco.aci.aci_epg), and M(cisco.aci.aci_contract) modules can be used for this.
+options:
+ ap:
+ description:
+ - Name of an existing application network profile, that will contain the EPGs.
+ type: str
+ aliases: [ app_profile, app_profile_name ]
+ contract:
+ description:
+ - The name of the contract.
+ type: str
+ aliases: [ contract_name ]
+ contract_type:
+ description:
+ - Determines if the EPG should Provide or Consume the Contract.
+ type: str
+ required: yes
+ choices: [ consumer, provider ]
+ epg:
+ description:
+ - The name of the end point group.
+ type: str
+ aliases: [ epg_name ]
+ priority:
+ description:
+ - QoS class.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ level1, level2, level3, unspecified ]
+ provider_match:
+ description:
+ - The matching algorithm for Provided Contracts.
+ - The APIC defaults to C(at_least_one) when unset during creation.
+ type: str
+ choices: [ all, at_least_one, at_most_one, none ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_ap
+- module: cisco.aci.aci_epg
+- module: cisco.aci.aci_contract
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(fv:RsCons) and B(fv:RsProv).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Add a new contract to EPG binding
+ cisco.aci.aci_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: anstest
+ epg: anstest
+ contract: anstest_http
+ contract_type: provider
+ state: present
+ delegate_to: localhost
+
+- name: Remove an existing contract to EPG binding
+ cisco.aci.aci_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: anstest
+ epg: anstest
+ contract: anstest_http
+ contract_type: provider
+ state: absent
+ delegate_to: localhost
+
+- name: Query a specific contract to EPG binding
+ cisco.aci.aci_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: anstest
+ epg: anstest
+ contract: anstest_http
+ contract_type: provider
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all provider contract to EPG bindings
+ cisco.aci.aci_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ contract_type: provider
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+ACI_CLASS_MAPPING = dict(
+ consumer={
+ 'class': 'fvRsCons',
+ 'rn': 'rscons-',
+ },
+ provider={
+ 'class': 'fvRsProv',
+ 'rn': 'rsprov-',
+ },
+)
+
+PROVIDER_MATCH_MAPPING = dict(
+ all='All',
+ at_least_one='AtleastOne',
+ at_most_one='AtmostOne',
+ none='None',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ contract_type=dict(type='str', required=True, choices=['consumer', 'provider']),
+ ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects
+ epg=dict(type='str', aliases=['epg_name']), # Not required for querying all objects
+ contract=dict(type='str', aliases=['contract_name']), # Not required for querying all objects
+ priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),
+ provider_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['ap', 'contract', 'epg', 'tenant']],
+ ['state', 'present', ['ap', 'contract', 'epg', 'tenant']],
+ ],
+ )
+
+ ap = module.params.get('ap')
+ contract = module.params.get('contract')
+ contract_type = module.params.get('contract_type')
+ epg = module.params.get('epg')
+ priority = module.params.get('priority')
+ provider_match = module.params.get('provider_match')
+ if provider_match is not None:
+ provider_match = PROVIDER_MATCH_MAPPING[provider_match]
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+
+ aci_class = ACI_CLASS_MAPPING[contract_type]["class"]
+ aci_rn = ACI_CLASS_MAPPING[contract_type]["rn"]
+
+ if contract_type == "consumer" and provider_match is not None:
+ module.fail_json(msg="the 'provider_match' is only configurable for Provided Contracts")
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvAp',
+ aci_rn='ap-{0}'.format(ap),
+ module_object=ap,
+ target_filter={'name': ap},
+ ),
+ subclass_2=dict(
+ aci_class='fvAEPg',
+ aci_rn='epg-{0}'.format(epg),
+ module_object=epg,
+ target_filter={'name': epg},
+ ),
+ subclass_3=dict(
+ aci_class=aci_class,
+ aci_rn='{0}{1}'.format(aci_rn, contract),
+ module_object=contract,
+ target_filter={'tnVzBrCPName': contract},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=aci_class,
+ class_config=dict(
+ matchT=provider_match,
+ prio=priority,
+ tnVzBrCPName=contract,
+ ),
+ )
+
+ aci.get_diff(aci_class=aci_class)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_master.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_master.py
new file mode 100644
index 00000000..d2368f7d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_contract_master.py
@@ -0,0 +1,302 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_epg_to_contract_master
+short_description: Manage End Point Group (EPG) contract master relationships (fv:RsSecInherited)
+description:
+- Manage End Point Groups (EPG) contract master relationships on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ required: yes
+ ap:
+ description:
+ - Name of an existing application network profile, that will contain the EPGs.
+ type: str
+ required: yes
+ aliases: [ app_profile, app_profile_name ]
+ epg:
+ description:
+ - Name of the end point group.
+ type: str
+ required: yes
+ aliases: [ epg_name, name ]
+ contract_master_ap:
+ description:
+ - Name of the application profile where the contract master EPG is.
+ type: str
+ contract_master_epg:
+ description:
+ - Name of the end point group which serves as contract master.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(app_profile) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_ap) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_epg
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:AEPg).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Cindy Zhao (@cizhao)
+'''
+
+EXAMPLES = r'''
+- name: Add contract master
+ cisco.aci.aci_epg_to_contract_master:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: apName
+ epg: epgName
+ contract_master_ap: ap
+ contract_master_epg: epg
+ state: present
+ delegate_to: localhost
+
+- name: Remove contract master
+ cisco.aci.aci_epg_to_contract_master:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: apName
+ epg: epgName
+ contract_master_ap: ap
+ contract_master_epg: epg
+ state: absent
+ delegate_to: localhost
+
+- name: Query contract master
+ cisco.aci.aci_epg_to_contract_master:
+ host: apic_host
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: apName
+ epg: epgName
+ contract_master_ap: ap
+ contract_master_epg: epg
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name'], required=True),
+ ap=dict(type='str', aliases=['app_profile', 'app_profile_name'], required=True),
+ epg=dict(type='str', aliases=['epg_name', 'name'], required=True),
+ contract_master_ap=dict(type='str'),
+ contract_master_epg=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['contract_master_ap', 'contract_master_epg']],
+ ['state', 'present', ['contract_master_ap', 'contract_master_epg']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ tenant = module.params.get('tenant')
+ ap = module.params.get('ap')
+ epg = module.params.get('epg')
+ contract_master_ap = module.params.get('contract_master_ap')
+ contract_master_epg = module.params.get('contract_master_epg')
+ state = module.params.get('state')
+
+ contract_master = 'uni/tn-{0}/ap-{1}/epg-{2}'.format(tenant, contract_master_ap, contract_master_epg)
+
+ child_configs = []
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvAp',
+ aci_rn='ap-{0}'.format(ap),
+ module_object=ap,
+ target_filter={'name': ap},
+ ),
+ subclass_2=dict(
+ aci_class='fvAEPg',
+ aci_rn='epg-{0}'.format(epg),
+ module_object=epg,
+ target_filter={'name': epg},
+ ),
+ subclass_3=dict(
+ aci_class='fvRsSecInherited',
+ aci_rn='rssecInherited-[{0}]'.format(contract_master),
+ module_object=contract_master,
+ target_filter={'tDn': contract_master},
+ ),
+ child_classes=[],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvRsSecInherited',
+ class_config=dict(
+ tDn=contract_master
+ ),
+ child_configs=child_configs
+ )
+
+ aci.get_diff(aci_class='fvRsSecInherited')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py
new file mode 100644
index 00000000..d4b8ea58
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_epg_to_domain.py
@@ -0,0 +1,441 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Jacob McGill <jmcgill298>
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_epg_to_domain
+short_description: Bind EPGs to Domains (fv:RsDomAtt)
+description:
+- Bind EPGs to Physical and Virtual Domains on Cisco ACI fabrics.
+options:
+ allow_useg:
+ description:
+ - Allows micro-segmentation.
+ - The APIC defaults to C(encap) when unset during creation.
+ type: str
+ choices: [ encap, useg ]
+ ap:
+ description:
+ - Name of an existing application network profile, that will contain the EPGs.
+ type: str
+ aliases: [ app_profile, app_profile_name ]
+ deploy_immediacy:
+ description:
+ - Determines when the policy is pushed to hardware Policy CAM.
+ - The APIC defaults to C(lazy) when unset during creation.
+ type: str
+ choices: [ immediate, lazy ]
+ domain:
+ description:
+ - Name of the physical or virtual domain being associated with the EPG.
+ type: str
+ aliases: [ domain_name, domain_profile ]
+ domain_type:
+ description:
+ - Specify whether the Domain is a physical (phys), a virtual (vmm) or an L2 external domain association (l2dom).
+ type: str
+ choices: [ l2dom, phys, vmm ]
+ aliases: [ type ]
+ encap:
+ description:
+ - The VLAN encapsulation for the EPG when binding a VMM Domain with static C(encap_mode).
+ - This acts as the secondary encap when using useg.
+ - Accepted values range between C(1) and C(4096).
+ type: int
+ encap_mode:
+ description:
+ - The encapsulation method to be used.
+ - The APIC defaults to C(auto) when unset during creation.
+ - If vxlan is selected, switching_mode must be "AVE".
+ type: str
+ choices: [ auto, vlan, vxlan ]
+ switching_mode:
+ description:
+ - Switching Mode used by the switch
+ type: str
+ choices: [ AVE, native ]
+ default: native
+ epg:
+ description:
+ - Name of the end point group.
+ type: str
+ aliases: [ epg_name, name ]
+ netflow:
+ description:
+ - Determines if netflow should be enabled.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ primary_encap:
+ description:
+ - Determines the primary VLAN ID when using useg.
+ - Accepted values range between C(1) and C(4096).
+ type: int
+ resolution_immediacy:
+ description:
+ - Determines when the policies should be resolved and available.
+ - The APIC defaults to C(lazy) when unset during creation.
+ type: str
+ choices: [ immediate, lazy, pre-provision ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ promiscuous:
+ description:
+ - Allow/Disallow promiscuous mode in vmm domain
+ type: str
+ choices: [ accept, reject ]
+ default: reject
+ vm_provider:
+ description:
+ - The VM platform for VMM Domains.
+ - Support for Kubernetes was added in ACI v3.0.
+ - Support for CloudFoundry, OpenShift and Red Hat was added in ACI v3.1.
+ type: str
+ choices: [ cloudfoundry, kubernetes, microsoft, openshift, openstack, redhat, vmware ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant), C(ap), C(epg), and C(domain) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) M(cisco.aci.aci_ap), M(cisco.aci.aci_epg) M(cisco.aci.aci_domain) modules can be used for this.
+- OpenStack VMM domains must not be created using this module. The OpenStack VMM domain is created directly
+ by the Cisco APIC Neutron plugin as part of the installation and configuration.
+ This module can be used to query status of an OpenStack VMM domain.
+seealso:
+- module: cisco.aci.aci_ap
+- module: cisco.aci.aci_epg
+- module: cisco.aci.aci_domain
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:RsDomAtt).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Add a new physical domain to EPG binding
+ cisco.aci.aci_epg_to_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: anstest
+ epg: anstest
+ domain: anstest
+ domain_type: phys
+ state: present
+ delegate_to: localhost
+
+- name: Remove an existing physical domain to EPG binding
+ cisco.aci.aci_epg_to_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: anstest
+ epg: anstest
+ domain: anstest
+ domain_type: phys
+ state: absent
+ delegate_to: localhost
+
+- name: Query a specific physical domain to EPG binding
+ cisco.aci.aci_epg_to_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: anstest
+ ap: anstest
+ epg: anstest
+ domain: anstest
+ domain_type: phys
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all domain to EPG bindings
+ cisco.aci.aci_epg_to_domain:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+VM_PROVIDER_MAPPING = dict(
+ cloudfoundry='CloudFoundry',
+ kubernetes='Kubernetes',
+ microsoft='Microsoft',
+ openshift='OpenShift',
+ openstack='OpenStack',
+ redhat='Redhat',
+ vmware='VMware',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ allow_useg=dict(type='str', choices=['encap', 'useg']),
+ ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects
+ deploy_immediacy=dict(type='str', choices=['immediate', 'lazy']),
+ domain=dict(type='str', aliases=['domain_name', 'domain_profile']), # Not required for querying all objects
+ domain_type=dict(type='str', choices=['l2dom', 'phys', 'vmm'], aliases=['type']), # Not required for querying all objects
+ encap=dict(type='int'),
+ encap_mode=dict(type='str', choices=['auto', 'vlan', 'vxlan']),
+ switching_mode=dict(type='str', default='native', choices=['AVE', 'native']),
+ epg=dict(type='str', aliases=['name', 'epg_name']), # Not required for querying all objects
+ netflow=dict(type='bool'),
+ primary_encap=dict(type='int'),
+ resolution_immediacy=dict(type='str', choices=['immediate', 'lazy', 'pre-provision']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ vm_provider=dict(type='str', choices=['cloudfoundry', 'kubernetes', 'microsoft', 'openshift', 'openstack', 'redhat', 'vmware']),
+ promiscuous=dict(type='str', default='reject', choices=['accept', 'reject']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['domain_type', 'vmm', ['vm_provider']],
+ ['state', 'absent', ['ap', 'domain', 'domain_type', 'epg', 'tenant']],
+ ['state', 'present', ['ap', 'domain', 'domain_type', 'epg', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ allow_useg = module.params.get('allow_useg')
+ ap = module.params.get('ap')
+ deploy_immediacy = module.params.get('deploy_immediacy')
+ domain = module.params.get('domain')
+ domain_type = module.params.get('domain_type')
+ vm_provider = module.params.get('vm_provider')
+ promiscuous = module.params.get('promiscuous')
+ encap = module.params.get('encap')
+ if encap is not None:
+ if encap in range(1, 4097):
+ encap = 'vlan-{0}'.format(encap)
+ else:
+ module.fail_json(msg='Valid VLAN assignments are from 1 to 4096')
+ encap_mode = module.params.get('encap_mode')
+ switching_mode = module.params.get('switching_mode')
+ epg = module.params.get('epg')
+ netflow = aci.boolean(module.params.get('netflow'), 'enabled', 'disabled')
+ primary_encap = module.params.get('primary_encap')
+ if primary_encap is not None:
+ if primary_encap in range(1, 4097):
+ primary_encap = 'vlan-{0}'.format(primary_encap)
+ else:
+ module.fail_json(msg='Valid VLAN assignments are from 1 to 4096')
+ resolution_immediacy = module.params.get('resolution_immediacy')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+
+ if domain_type in ['l2dom', 'phys'] and vm_provider is not None:
+ module.fail_json(msg="Domain type '%s' cannot have a 'vm_provider'" % domain_type)
+
+ child_classes = None
+ child_configs = None
+
+ # Compile the full domain for URL building
+ if domain_type == 'vmm':
+ epg_domain = 'uni/vmmp-{0}/dom-{1}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
+ child_configs = [dict(vmmSecP=dict(attributes=dict(allowPromiscuous=promiscuous)))]
+ child_classes = ['vmmSecP']
+ elif domain_type == 'l2dom':
+ epg_domain = 'uni/l2dom-{0}'.format(domain)
+ elif domain_type == 'phys':
+ epg_domain = 'uni/phys-{0}'.format(domain)
+ else:
+ epg_domain = None
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvAp',
+ aci_rn='ap-{0}'.format(ap),
+ module_object=ap,
+ target_filter={'name': ap},
+ ),
+ subclass_2=dict(
+ aci_class='fvAEPg',
+ aci_rn='epg-{0}'.format(epg),
+ module_object=epg,
+ target_filter={'name': epg},
+ ),
+ subclass_3=dict(
+ aci_class='fvRsDomAtt',
+ aci_rn='rsdomAtt-[{0}]'.format(epg_domain),
+ module_object=epg_domain,
+ target_filter={'tDn': epg_domain},
+ ),
+ child_classes=child_classes,
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvRsDomAtt',
+ class_config=dict(
+ classPref=allow_useg,
+ encap=encap,
+ encapMode=encap_mode,
+ switchingMode=switching_mode,
+ instrImedcy=deploy_immediacy,
+ netflowPref=netflow,
+ primaryEncap=primary_encap,
+ resImedcy=resolution_immediacy,
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='fvRsDomAtt')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_node.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_node.py
new file mode 100644
index 00000000..b1ea5f91
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_node.py
@@ -0,0 +1,288 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_fabric_node
+short_description: Manage Fabric Node Members (fabric:NodeIdentP)
+description:
+- Manage Fabric Node Members on Cisco ACI fabrics.
+options:
+ pod_id:
+ description:
+ - The pod id of the new Fabric Node Member.
+ type: int
+ serial:
+ description:
+ - Serial Number for the new Fabric Node Member.
+ type: str
+ aliases: [ serial_number ]
+ node_id:
+ description:
+ - Node ID Number for the new Fabric Node Member.
+ type: int
+ switch:
+ description:
+ - Switch Name for the new Fabric Node Member.
+ type: str
+ aliases: [ name, switch_name ]
+ description:
+ description:
+ - Description for the new Fabric Node Member.
+ type: str
+ aliases: [ descr ]
+ role:
+ description:
+ - Role for the new Fabric Node Member.
+ type: str
+ aliases: [ role_name ]
+ choices: [ leaf, spine, unspecified ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fabric:NodeIdentP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+'''
+
+EXAMPLES = r'''
+- name: Add fabric node
+ cisco.aci.aci_fabric_node:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ serial: FDO2031124L
+ node_id: 1011
+ switch: fab4-sw1011
+ state: present
+ delegate_to: localhost
+
+- name: Remove fabric node
+ cisco.aci.aci_fabric_node:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ serial: FDO2031124L
+ node_id: 1011
+ state: absent
+ delegate_to: localhost
+
+- name: Query fabric nodes
+ cisco.aci.aci_fabric_node:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: '?rsp-prop-include=config-only'
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+# NOTE: (This problem is also present on the APIC GUI)
+# NOTE: When specifying a C(role) the new Fabric Node Member will be created but Role on GUI will be "unknown", hence not what seems to be a module problem
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ description=dict(type='str', aliases=['descr']),
+ node_id=dict(type='int'), # Not required for querying all objects
+ pod_id=dict(type='int'),
+ role=dict(type='str', choices=['leaf', 'spine', 'unspecified'], aliases=['role_name']),
+ serial=dict(type='str', aliases=['serial_number']), # Not required for querying all objects
+ switch=dict(type='str', aliases=['name', 'switch_name']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['node_id', 'serial']],
+ ['state', 'present', ['node_id', 'serial']],
+ ],
+ )
+
+ pod_id = module.params.get('pod_id')
+ serial = module.params.get('serial')
+ node_id = module.params.get('node_id')
+ switch = module.params.get('switch')
+ description = module.params.get('description')
+ role = module.params.get('role')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fabricNodeIdentP',
+ aci_rn='controller/nodeidentpol/nodep-{0}'.format(serial),
+ module_object=serial,
+ target_filter={'serial': serial},
+ )
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fabricNodeIdentP',
+ class_config=dict(
+ descr=description,
+ name=switch,
+ nodeId=node_id,
+ podId=pod_id,
+ # NOTE: Originally we were sending 'rn', but now we need 'dn' for idempotency
+ # FIXME: Did this change with ACI version ?
+ dn='uni/controller/nodeidentpol/nodep-{0}'.format(serial),
+ # rn='nodep-{0}'.format(serial),
+ role=role,
+ serial=serial,
+ nameAlias=name_alias,
+ )
+ )
+
+ aci.get_diff(aci_class='fabricNodeIdentP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json(**aci.result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_scheduler.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_scheduler.py
new file mode 100644
index 00000000..ecc91330
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_fabric_scheduler.py
@@ -0,0 +1,331 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+---
+module: aci_fabric_scheduler
+
+short_description: This modules creates ACI schedulers.
+
+
+description:
+ - With the module you can create schedule policies that can be a shell, onetime execution or recurring
+
+options:
+ name:
+ description:
+ - The name of the Scheduler.
+ type: str
+ aliases: [ scheduler_name ]
+ description:
+ description:
+ - Description for the Scheduler.
+ type: str
+ aliases: [ descr ]
+ recurring:
+ description:
+ - If you want to make the Scheduler a recurring it would be a "True" and for a
+ oneTime execution it would be "False". For a shell just exclude this option from
+ the task
+ type: bool
+ default: 'no'
+ windowname:
+ description:
+ - This is the name for your what recurring or oneTime execution
+ type: str
+ concurCap:
+ description:
+ - This is the amount of devices that can be executed on at a time
+ type: int
+ maxTime:
+ description:
+ - This is the amount MAX amount of time a process can be executed
+ type: str
+ date:
+ description:
+ - This is the date and time that the scheduler will execute
+ type: str
+ hour:
+ description:
+ - This set the hour of execution
+ type: int
+ minute:
+ description:
+ - This sets the minute of execution, used in conjunction with hour
+ type: int
+ day:
+ description:
+ - This sets the day when execution will take place
+ type: str
+ default: "every-day"
+ choices: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday', 'even-day', 'odd-day', 'every-day']
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ default: present
+ choices: [ absent, present, query ]
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+
+author:
+ - Steven Gerhart (@sgerhart)
+'''
+
+EXAMPLES = r'''
+ - name: Simple Scheduler (Empty)
+ cisco.aci.aci_fabric_scheduler:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ name: simpleScheduler
+ state: present
+ - name: Remove Simple Scheduler
+ cisco.aci.aci_fabric_scheduler:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ name: simpleScheduler
+ state: absent
+ - name: One Time Scheduler
+ cisco.aci.aci_fabric_scheduler:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ name: OneTime
+ windowname: OneTime
+ recurring: False
+ concurCap: 20
+ date: "2018-11-20T24:00:00"
+ state: present
+ - name: Recurring Scheduler
+ cisco.aci.aci_fabric_scheduler:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ name: Recurring
+ windowname: Recurring
+ recurring: True
+ concurCap: 20
+ hour: 13
+ minute: 30
+ day: Tuesday
+ state: present
+'''
+
+RETURN = '''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ name=dict(type='str', aliases=['scheduler_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ windowname=dict(type='str'),
+ recurring=dict(type='bool'),
+ concurCap=dict(type='int'), # Number of devices it will run against concurrently
+ maxTime=dict(type='str'), # The amount of minutes a process will be able to run (unlimited or dd:hh:mm:ss)
+ date=dict(type='str'), # The date the process will run YYYY-MM-DDTHH:MM:SS
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ hour=dict(type='int'),
+ minute=dict(type='int'),
+ day=dict(type='str', default='every-day', choices=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
+ 'Saturday', 'Sunday', 'every-day', 'even-day', 'odd-day']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['name']],
+ ['state', 'present', ['name']],
+ ],
+ )
+
+ state = module.params.get('state')
+ name = module.params.get('name')
+ windowname = module.params.get('windowname')
+ recurring = module.params.get('recurring')
+ date = module.params.get('date')
+ hour = module.params.get('hour')
+ minute = module.params.get('minute')
+ maxTime = module.params.get('maxTime')
+ concurCap = module.params.get('concurCap')
+ day = module.params.get('day')
+ description = module.params.get('description')
+ name_alias = module.params.get('name_alias')
+
+ if recurring:
+ child_configs = [dict(trigRecurrWindowP=dict(attributes=dict(name=windowname, hour=hour, minute=minute,
+ procCa=maxTime, concurCap=concurCap, day=day,)))]
+ elif recurring is False:
+ child_configs = [dict(trigAbsWindowP=dict(attributes=dict(name=windowname, procCap=maxTime,
+ concurCap=concurCap, date=date,)))]
+ else:
+ child_configs = []
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='trigSchedP',
+ aci_rn='fabric/schedp-{0}'.format(name),
+ target_filter={'name': name},
+ module_object=name,
+ ),
+
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='trigSchedP',
+ class_config=dict(
+ name=name,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ child_configs=child_configs,
+
+ )
+
+ aci.get_diff(aci_class='trigSchedP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter.py
new file mode 100644
index 00000000..9b79eae9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter.py
@@ -0,0 +1,279 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_filter
+short_description: Manages top level filter objects (vz:Filter)
+description:
+- Manages top level filter objects on Cisco ACI fabrics.
+- This modules does not manage filter entries, see M(cisco.aci.aci_filter_entry) for this functionality.
+options:
+ filter:
+ description:
+ - The name of the filter.
+ type: str
+ aliases: [ filter_name, name ]
+ description:
+ description:
+ - Description for the filter.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(vz:Filter).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add a new filter to a tenant
+ cisco.aci.aci_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ filter: web_filter
+ description: Filter for web protocols
+ tenant: production
+ state: present
+ delegate_to: localhost
+
+- name: Remove a filter for a tenant
+ cisco.aci.aci_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ filter: web_filter
+ tenant: production
+ state: absent
+ delegate_to: localhost
+
+- name: Query a filter of a tenant
+ cisco.aci.aci_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ filter: web_filter
+ tenant: production
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all filters for a tenant
+ cisco.aci.aci_filter:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ filter=dict(type='str', aliases=['name', 'filter_name']), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['filter', 'tenant']],
+ ['state', 'present', ['filter', 'tenant']],
+ ],
+ )
+
+ filter_name = module.params.get('filter')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='vzFilter',
+ aci_rn='flt-{0}'.format(filter_name),
+ module_object=filter_name,
+ target_filter={'name': filter_name},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='vzFilter',
+ class_config=dict(
+ name=filter_name,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='vzFilter')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter_entry.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter_entry.py
new file mode 100644
index 00000000..babf6d9d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_filter_entry.py
@@ -0,0 +1,376 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_filter_entry
+short_description: Manage filter entries (vz:Entry)
+description:
+- Manage filter entries for a filter on Cisco ACI fabrics.
+options:
+ arp_flag:
+ description:
+ - The arp flag to use when the ether_type is arp.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ arp_reply, arp_request, unspecified ]
+ description:
+ description:
+ - Description for the Filter Entry.
+ type: str
+ aliases: [ descr ]
+ dst_port:
+ description:
+ - Used to set both destination start and end ports to the same value when ip_protocol is tcp or udp.
+ - Accepted values are any valid TCP/UDP port range.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ dst_port_end:
+ description:
+ - Used to set the destination end port when ip_protocol is tcp or udp.
+ - Accepted values are any valid TCP/UDP port range.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ dst_port_start:
+ description:
+ - Used to set the destination start port when ip_protocol is tcp or udp.
+ - Accepted values are any valid TCP/UDP port range.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ entry:
+ description:
+ - Then name of the Filter Entry.
+ type: str
+ aliases: [ entry_name, filter_entry, name ]
+ ether_type:
+ description:
+ - The Ethernet type.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ arp, fcoe, ip, mac_security, mpls_ucast, trill, unspecified ]
+ filter:
+ description:
+ - The name of Filter that the entry should belong to.
+ type: str
+ aliases: [ filter_name ]
+ icmp_msg_type:
+ description:
+ - ICMPv4 message type; used when ip_protocol is icmp.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ dst_unreachable, echo, echo_reply, src_quench, time_exceeded, unspecified ]
+ icmp6_msg_type:
+ description:
+ - ICMPv6 message type; used when ip_protocol is icmpv6.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ dst_unreachable, echo_request, echo_reply, neighbor_advertisement, neighbor_solicitation, redirect, time_exceeded, unspecified ]
+ ip_protocol:
+ description:
+ - The IP Protocol type when ether_type is ip.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ eigrp, egp, icmp, icmpv6, igmp, igp, l2tp, ospfigp, pim, tcp, udp, unspecified ]
+ state:
+ description:
+ - present, absent, query
+ type: str
+ default: present
+ choices: [ absent, present, query ]
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ stateful:
+ description:
+ - Determines the statefulness of the filter entry.
+ type: bool
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(filter) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_filter) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_filter
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(vz:Entry).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- cisco.aci.aci_filter_entry:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ state: "{{ state }}"
+ entry: "{{ entry }}"
+ tenant: "{{ tenant }}"
+ ether_name: "{{ ether_name }}"
+ icmp_msg_type: "{{ icmp_msg_type }}"
+ filter: "{{ filter }}"
+ descr: "{{ descr }}"
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+VALID_ARP_FLAGS = ['arp_reply', 'arp_request', 'unspecified']
+VALID_ETHER_TYPES = ['arp', 'fcoe', 'ip', 'mac_security', 'mpls_ucast', 'trill', 'unspecified']
+VALID_ICMP_TYPES = ['dst_unreachable', 'echo', 'echo_reply', 'src_quench', 'time_exceeded', 'unspecified']
+VALID_ICMP6_TYPES = ['dst_unreachable', 'echo_request', 'echo_reply', 'neighbor_advertisement',
+ 'neighbor_solicitation', 'redirect', 'time_exceeded', 'unspecified']
+VALID_IP_PROTOCOLS = ['eigrp', 'egp', 'icmp', 'icmpv6', 'igmp', 'igp', 'l2tp', 'ospfigp', 'pim', 'tcp', 'udp', 'unspecified']
+
+# mapping dicts are used to normalize the proposed data to what the APIC expects, which will keep diffs accurate
+ARP_FLAG_MAPPING = dict(arp_reply='reply', arp_request='req', unspecified=None)
+FILTER_PORT_MAPPING = {'443': 'https', '25': 'smtp', '80': 'http', '20': 'ftpData', '53': 'dns', '110': 'pop3', '554': 'rtsp'}
+ICMP_MAPPING = {'dst_unreachable': 'dst-unreach', 'echo': 'echo', 'echo_reply': 'echo-rep', 'src_quench': 'src-quench',
+ 'time_exceeded': 'time-exceeded', 'unspecified': 'unspecified', 'echo-rep': 'echo-rep', 'dst-unreach': 'dst-unreach'}
+ICMP6_MAPPING = dict(dst_unreachable='dst-unreach', echo_request='echo-req', echo_reply='echo-rep', neighbor_advertisement='nbr-advert',
+ neighbor_solicitation='nbr-solicit', redirect='redirect', time_exceeded='time-exceeded', unspecified='unspecified')
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ arp_flag=dict(type='str', choices=VALID_ARP_FLAGS),
+ description=dict(type='str', aliases=['descr']),
+ dst_port=dict(type='str'),
+ dst_port_end=dict(type='str'),
+ dst_port_start=dict(type='str'),
+ entry=dict(type='str', aliases=['entry_name', 'filter_entry', 'name']), # Not required for querying all objects
+ ether_type=dict(choices=VALID_ETHER_TYPES, type='str'),
+ filter=dict(type='str', aliases=['filter_name']), # Not required for querying all objects
+ icmp_msg_type=dict(type='str', choices=VALID_ICMP_TYPES),
+ icmp6_msg_type=dict(type='str', choices=VALID_ICMP6_TYPES),
+ ip_protocol=dict(choices=VALID_IP_PROTOCOLS, type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ stateful=dict(type='bool'),
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['entry', 'filter', 'tenant']],
+ ['state', 'present', ['entry', 'filter', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ arp_flag = module.params.get('arp_flag')
+ if arp_flag is not None:
+ arp_flag = ARP_FLAG_MAPPING.get(arp_flag)
+ description = module.params.get('description')
+ dst_port = module.params.get('dst_port')
+ if FILTER_PORT_MAPPING.get(dst_port) is not None:
+ dst_port = FILTER_PORT_MAPPING.get(dst_port)
+ dst_end = module.params.get('dst_port_end')
+ if FILTER_PORT_MAPPING.get(dst_end) is not None:
+ dst_end = FILTER_PORT_MAPPING.get(dst_end)
+ dst_start = module.params.get('dst_port_start')
+ if FILTER_PORT_MAPPING.get(dst_start) is not None:
+ dst_start = FILTER_PORT_MAPPING.get(dst_start)
+ entry = module.params.get('entry')
+ ether_type = module.params.get('ether_type')
+ filter_name = module.params.get('filter')
+ icmp_msg_type = module.params.get('icmp_msg_type')
+ if icmp_msg_type is not None:
+ icmp_msg_type = ICMP_MAPPING.get(icmp_msg_type)
+ icmp6_msg_type = module.params.get('icmp6_msg_type')
+ if icmp6_msg_type is not None:
+ icmp6_msg_type = ICMP6_MAPPING.get(icmp6_msg_type)
+ ip_protocol = module.params.get('ip_protocol')
+ state = module.params.get('state')
+ stateful = aci.boolean(module.params.get('stateful'))
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ # validate that dst_port is not passed with dst_start or dst_end
+ if dst_port is not None and (dst_end is not None or dst_start is not None):
+ module.fail_json(msg="Parameter 'dst_port' cannot be used with 'dst_end' and 'dst_start'")
+ elif dst_port is not None:
+ dst_end = dst_port
+ dst_start = dst_port
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='vzFilter',
+ aci_rn='flt-{0}'.format(filter_name),
+ module_object=filter_name,
+ target_filter={'name': filter_name},
+ ),
+ subclass_2=dict(
+ aci_class='vzEntry',
+ aci_rn='e-{0}'.format(entry),
+ module_object=entry,
+ target_filter={'name': entry},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='vzEntry',
+ class_config=dict(
+ arpOpc=arp_flag,
+ descr=description,
+ dFromPort=dst_start,
+ dToPort=dst_end,
+ etherT=ether_type,
+ icmpv4T=icmp_msg_type,
+ icmpv6T=icmp6_msg_type,
+ name=entry,
+ prot=ip_protocol,
+ stateful=stateful,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='vzEntry')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group.py
new file mode 100644
index 00000000..9c25c344
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group.py
@@ -0,0 +1,238 @@
+#!/usr/bin/python
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+---
+module: aci_firmware_group
+
+short_description: This module creates a firmware group
+
+
+description:
+ - This module creates a firmware group, so that you can apply firmware policy to nodes.
+options:
+ group:
+ description:
+ - This the name of the firmware group
+ type: str
+ firmwarepol:
+ description:
+ - This is the name of the firmware policy, which was create by aci_firmware_policy. It is important that
+ - you use the same name as the policy created with aci_firmware_policy
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ default: present
+ choices: [ absent, present, query ]
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+author:
+ - Steven Gerhart (@sgerhart)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+ - name: firmware group
+ cisco.aci.aci_firmware_group:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ group: testingfwgrp1
+ firmwarepol: test2FrmPol
+ state: present
+'''
+RETURN = '''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ group=dict(type='str'), # Not required for querying all objects
+ firmwarepol=dict(type='str'), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['group']],
+ ['state', 'present', ['group', 'firmwarepol']],
+ ],
+ )
+
+ state = module.params.get('state')
+ group = module.params.get('group')
+ firmwarepol = module.params.get('firmwarepol')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='firmwareFwGrp',
+ aci_rn='fabric/fwgrp-{0}'.format(group),
+ target_filter={'name': group},
+ module_object=group,
+ ),
+ child_classes=['firmwareRsFwgrpp'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='firmwareFwGrp',
+ class_config=dict(
+ name=group,
+ nameAlias=name_alias,
+ ),
+ child_configs=[
+ dict(
+ firmwareRsFwgrpp=dict(
+ attributes=dict(
+ tnFirmwareFwPName=firmwarepol,
+ ),
+ ),
+ ),
+ ],
+
+ )
+
+ aci.get_diff(aci_class='firmwareFwGrp')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group_node.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group_node.py
new file mode 100644
index 00000000..79a03fd7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_group_node.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+---
+module: aci_firmware_group_node
+
+short_description: This modules adds and remove nodes from the firmware group
+
+
+description:
+ - This module addes/deletes a node to the firmware group. This modules assigns 1 node at a time.
+
+options:
+ group:
+ description:
+ - This is the name of the firmware group
+ type: str
+ node:
+ description:
+ - The node to be added to the firmware group - the value equals the NodeID
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ default: present
+ choices: [ absent, present, query ]
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+
+author:
+ - Steven Gerhart (@sgerhart)
+'''
+
+EXAMPLES = r'''
+ - name: add firmware group node
+ cisco.aci.aci_firmware_group_node:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ group: testingfwgrp
+ node: 1001
+ state: present
+ - name: Remove firmware group node
+ cisco.aci.aci_firmware_group_node:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ group: testingfwgrp
+ node: 1001
+ state: absent
+'''
+
+RETURN = '''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ group=dict(type='str'), # Not required for querying all objects
+ node=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['node', 'group']],
+ ['state', 'present', ['node', 'group']],
+ ],
+ )
+
+ state = module.params.get('state')
+ group = module.params.get('group')
+ node = module.params.get('node')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='firmwareFwGrp',
+ aci_rn='fabric/fwgrp-{0}'.format(group),
+ target_filter={'name': group},
+ module_object=group,
+ ),
+ subclass_1=dict(
+ aci_class='fabricNodeBlk',
+ aci_rn='nodeblk-blk{0}-{0}'.format(node),
+ target_filter={'name': node},
+ module_object=node,
+ ),
+
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fabricNodeBlk',
+ class_config=dict(
+ from_=node,
+ to_=node,
+ nameAlias=name_alias,
+ ),
+
+
+ )
+
+ aci.get_diff(aci_class='fabricNodeBlk')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_policy.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_policy.py
new file mode 100644
index 00000000..5c466ddc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_policy.py
@@ -0,0 +1,253 @@
+#!/usr/bin/python
+
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+---
+module: aci_firmware_policy
+
+short_description: This creates a firmware policy
+
+
+description:
+ - This module creates a firmware policy for firmware groups. The firmware policy is create first and then
+ - referenced by the firmware group. You will assign the firmware and specify if you want to ignore the compatibility
+ - check
+options:
+ name:
+ description:
+ - Name of the firmware policy
+ type: str
+ version:
+ description:
+ - The version of the firmware associated with this policy. This value is very import as well as constructing
+ - it correctly. The syntax for this field is n9000-xx.x. If you look at the firmware repository using the UI
+ - each version will have a "Full Version" column, this is the value you need to use. So, if the Full Version
+ - is 13.1(1i), the value for this field would be n9000-13.1(1i)
+ type: str
+ ignoreCompat:
+ description:
+ - Check if compatibility checks should be ignored
+ type: bool
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [absent, present, query]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+
+author:
+ - Steven Gerhart (@sgerhart)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+ - name: firmware policy
+ cisco.aci.aci_firmware_policy:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ name: test2FrmPol
+ version: n9000-13.2(1m)
+ ignoreCompat: False
+ state: present
+
+'''
+
+RETURN = '''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ name=dict(type='str'), # Not required for querying all objects
+ version=dict(type='str'),
+ ignoreCompat=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['name']],
+ ['state', 'present', ['name', 'version']],
+ ],
+ )
+
+ state = module.params.get('state')
+ name = module.params.get('name')
+ version = module.params.get('version')
+ name_alias = module.params.get('name_alias')
+
+ if module.params.get('ignoreCompat'):
+ ignore = 'yes'
+ else:
+ ignore = 'no'
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='firmwareFwP',
+ aci_rn='fabric/fwpol-{0}'.format(name),
+ target_filter={'name': name},
+ module_object=name,
+ ),
+
+
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='firmwareFwP',
+ class_config=dict(
+ name=name,
+ version=version,
+ ignoreCompat=ignore,
+ nameAlias=name_alias,
+ ),
+
+ )
+
+ aci.get_diff(aci_class='firmwareFwP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_source.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_source.py
new file mode 100644
index 00000000..52946578
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_firmware_source.py
@@ -0,0 +1,303 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_firmware_source
+short_description: Manage firmware image sources (firmware:OSource)
+description:
+- Manage firmware image sources on Cisco ACI fabrics.
+options:
+ source:
+ description:
+ - The identifying name for the outside source of images, such as an HTTP or SCP server.
+ type: str
+ aliases: [ name, source_name ]
+ polling_interval:
+ description:
+ - Polling interval in minutes.
+ type: int
+ url_protocol:
+ description:
+ - The Firmware download protocol.
+ type: str
+ choices: [ http, local, scp, usbkey ]
+ default: scp
+ aliases: [ url_proto ]
+ url:
+ description:
+ The firmware URL for the image(s) on the source.
+ type: str
+ url_password:
+ description:
+ The Firmware password or key string.
+ type: str
+ url_username:
+ description:
+ The username for the source.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(firmware:OSource).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add firmware source
+ cisco.aci.aci_firmware_source:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ source: aci-msft-pkg-3.1.1i.zip
+ url: foo.bar.cisco.com/download/cisco/aci/aci-msft-pkg-3.1.1i.zip
+ url_protocol: http
+ state: present
+ delegate_to: localhost
+
+- name: Remove firmware source
+ cisco.aci.aci_firmware_source:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ source: aci-msft-pkg-3.1.1i.zip
+ state: absent
+ delegate_to: localhost
+
+- name: Query a specific firmware source
+ cisco.aci.aci_firmware_source:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ source: aci-msft-pkg-3.1.1i.zip
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all firmware sources
+ cisco.aci.aci_firmware_source:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ source=dict(type='str', aliases=['name', 'source_name']), # Not required for querying all objects
+ polling_interval=dict(type='int'),
+ url=dict(type='str'),
+ url_username=dict(type='str'),
+ url_password=dict(type='str', no_log=True),
+ url_protocol=dict(type='str', default='scp', choices=['http', 'local', 'scp', 'usbkey'], aliases=['url_proto']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['source']],
+ ['state', 'present', ['url_protocol', 'source', 'url']],
+ ],
+ )
+
+ polling_interval = module.params.get('polling_interval')
+ url_protocol = module.params.get('url_protocol')
+ state = module.params.get('state')
+ source = module.params.get('source')
+ url = module.params.get('url')
+ url_password = module.params.get('url_password')
+ url_username = module.params.get('url_username')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fabricInst',
+ aci_rn='fabric',
+ module_object='fabric',
+ target_filter={'name': 'fabric'},
+ ),
+ subclass_1=dict(
+ aci_class='firmwareRepoP',
+ aci_rn='fwrepop',
+ module_object='fwrepop',
+ target_filter={'name': 'fwrepop'},
+ ),
+ subclass_2=dict(
+ aci_class='firmwareOSource',
+ aci_rn='osrc-{0}'.format(source),
+ module_object=source,
+ target_filter={'name': source},
+ ),
+ config_only=False,
+ )
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='firmwareOSource',
+ class_config=dict(
+ name=source,
+ url=url,
+ password=url_password,
+ pollingInterval=polling_interval,
+ proto=url_protocol,
+ user=url_username,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='firmwareOSource')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_cdp.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_cdp.py
new file mode 100644
index 00000000..635c1799
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_cdp.py
@@ -0,0 +1,266 @@
+#!/usr/bin/python
+
+# Copyright: (c) 2019, Tim Knipper <tim.knipper@gmail.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_cdp
+short_description: Manage CDP interface policies (cdp:IfPol)
+description:
+- Manage CDP interface policies on Cisco ACI fabrics.
+options:
+ cdp_policy:
+ description:
+ - The CDP interface policy name.
+ type: str
+ aliases: [ cdp_interface, name ]
+ description:
+ description:
+ - The description for the CDP interface policy name.
+ type: str
+ aliases: [ descr ]
+ admin_state:
+ description:
+ - Enable or Disable CDP state.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(cdp:IfPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Tim Knipper (@tknipper11)
+'''
+
+EXAMPLES = r'''
+- name: Create CDP Interface Policy to enable CDP
+ cisco.aci.aci_interface_policy_cdp:
+ name: Ansible_CDP_Interface_Policy
+ host: apic.example.com
+ username: admin
+ password: adminpass
+ admin_state: true
+ state: present
+
+- name: Create CDP Interface Policy to disable CDP
+ cisco.aci.aci_interface_policy_cdp:
+ name: Ansible_CDP_Interface_Policy
+ host: apic.example.com
+ username: admin
+ password: adminpass
+ admin_state: false
+ state: present
+
+- name: Remove CDP Interface Policy
+ cisco.aci.aci_interface_policy_cdp:
+ name: Ansible_CDP_Interface_Policy
+ host: apic.example.com
+ username: admin
+ password: adminpass
+ output_level: debug
+ state: absent
+
+- name: Query CDP Policy
+ cisco.aci.aci_interface_policy_cdp:
+ host: apic.example.com
+ username: admin
+ password: adminpass
+ state: query
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "cdpIfPol": {
+ "attributes": {
+ "adminSt": "disabled",
+ "annotation": "",
+ "descr": "Ansible Created CDP Test Policy",
+ "dn": "uni/infra/cdpIfP-Ansible_CDP_Test_Policy",
+ "name": "Ansible_CDP_Test_Policy",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ cdp_policy=dict(type='str', required=False, aliases=['cdp_interface', 'name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ admin_state=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['cdp_policy']],
+ ['state', 'present', ['cdp_policy']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ cdp_policy = module.params.get('cdp_policy')
+ description = module.params.get('description')
+ admin_state = aci.boolean(module.params.get('admin_state'), 'enabled', 'disabled')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='cdpIfPol',
+ aci_rn='infra/cdpIfP-{0}'.format(cdp_policy),
+ module_object=cdp_policy,
+ target_filter={'name': cdp_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='cdpIfPol',
+ class_config=dict(
+ name=cdp_policy,
+ descr=description,
+ adminSt=admin_state,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='cdpIfPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_fc.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_fc.py
new file mode 100644
index 00000000..d2eb1595
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_fc.py
@@ -0,0 +1,240 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_fc
+short_description: Manage Fibre Channel interface policies (fc:IfPol)
+description:
+- Manage ACI Fiber Channel interface policies on Cisco ACI fabrics.
+options:
+ fc_policy:
+ description:
+ - The name of the Fiber Channel interface policy.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description of the Fiber Channel interface policy.
+ type: str
+ aliases: [ descr ]
+ port_mode:
+ description:
+ - The Port Mode to use.
+ - The APIC defaults to C(f) when unset during creation.
+ type: str
+ choices: [ f, np ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fc:IfPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: Add a Fibre Channel interface policy
+ cisco.aci.aci_interface_policy_fc:
+ host: '{{ hostname }}'
+ username: '{{ username }}'
+ password: '{{ password }}'
+ fc_policy: '{{ fc_policy }}'
+ port_mode: '{{ port_mode }}'
+ description: '{{ description }}'
+ state: present
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ fc_policy=dict(type='str', aliases=['name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ port_mode=dict(type='str', choices=['f', 'np']), # No default provided on purpose
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['fc_policy']],
+ ['state', 'present', ['fc_policy']],
+ ],
+ )
+
+ fc_policy = module.params.get('fc_policy')
+ port_mode = module.params.get('port_mode')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fcIfPol',
+ aci_rn='infra/fcIfPol-{0}'.format(fc_policy),
+ module_object=fc_policy,
+ target_filter={'name': fc_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fcIfPol',
+ class_config=dict(
+ name=fc_policy,
+ descr=description,
+ portMode=port_mode,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='fcIfPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_l2.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_l2.py
new file mode 100644
index 00000000..bd74c922
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_l2.py
@@ -0,0 +1,265 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_l2
+short_description: Manage Layer 2 interface policies (l2:IfPol)
+description:
+- Manage Layer 2 interface policies on Cisco ACI fabrics.
+options:
+ l2_policy:
+ description:
+ - The name of the Layer 2 interface policy.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description of the Layer 2 interface policy.
+ type: str
+ aliases: [ descr ]
+ qinq:
+ description:
+ - Determines if QinQ is disabled or if the port should be considered a core or edge port.
+ - The APIC defaults to C(disabled) when unset during creation.
+ type: str
+ choices: [ core, disabled, edge ]
+ vepa:
+ description:
+ - Determines if Virtual Ethernet Port Aggregator is disabled or enabled.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ vlan_scope:
+ description:
+ - The scope of the VLAN.
+ - The APIC defaults to C(global) when unset during creation.
+ type: str
+ choices: [ global, portlocal ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l2:IfPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: Add a Layer 2 interface policy
+ cisco.aci.aci_interface_policy_l2:
+ host: '{{ hostname }}'
+ username: '{{ username }}'
+ password: '{{ password }}'
+ l2_policy: '{{ l2_policy }}'
+ vlan_scope: '{{ vlan_policy }}'
+ description: '{{ description }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+# Mapping dicts are used to normalize the proposed data to what the APIC expects, which will keep diffs accurate
+QINQ_MAPPING = dict(
+ core='corePort',
+ disabled='disabled',
+ edge='edgePort',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ l2_policy=dict(type='str', aliases=['name']), # Not required for querying all policies
+ description=dict(type='str', aliases=['descr']),
+ vlan_scope=dict(type='str', choices=['global', 'portlocal']), # No default provided on purpose
+ qinq=dict(type='str', choices=['core', 'disabled', 'edge']),
+ vepa=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['l2_policy']],
+ ['state', 'present', ['l2_policy']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ l2_policy = module.params.get('l2_policy')
+ vlan_scope = module.params.get('vlan_scope')
+ qinq = module.params.get('qinq')
+ if qinq is not None:
+ qinq = QINQ_MAPPING.get(qinq)
+ vepa = aci.boolean(module.params.get('vepa'), 'enabled', 'disabled')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='l2IfPol',
+ aci_rn='infra/l2IfP-{0}'.format(l2_policy),
+ module_object=l2_policy,
+ target_filter={'name': l2_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='l2IfPol',
+ class_config=dict(
+ name=l2_policy,
+ descr=description,
+ vlanScope=vlan_scope,
+ qinq=qinq, vepa=vepa,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='l2IfPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_breakout_port_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_breakout_port_group.py
new file mode 100644
index 00000000..2646198b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_breakout_port_group.py
@@ -0,0 +1,259 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Cindy Zhao <cizhao@cisco.com>
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_leaf_breakout_port_group
+short_description: Manage fabric interface policy leaf breakout port group (infra:BrkoutPortGrp)
+description:
+- Manage fabric interface policy leaf breakout port group on Cisco ACI fabrics.
+options:
+ breakout_port_group:
+ description:
+ - Name of the leaf breakout port group to be added/deleted.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - Description for the leaf breakout port group to be created.
+ type: str
+ aliases: [ descr ]
+ breakout_map:
+ description:
+ - The mapping of breakout port.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(infra:BrkoutPortGrp).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Cindy Zhao (@cizhao)
+'''
+
+EXAMPLES = r'''
+- name: Create a Leaf Breakout Port Group
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ breakout_port_group: BreakoutPortName
+ breakout_map: 10g-4x
+ state: present
+ delegate_to: localhost
+
+- name: Query all Leaf Breakout Port Groups of type link
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a specific Leaf Breakout Port Group
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ breakout_port_group: BreakoutPortName
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Delete an Leaf Breakout Port Group
+ cisco.aci.aci_interface_policy_leaf_breakout_port_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ breakout_port_group: BreakoutPortName
+ state: absent
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ breakout_port_group=dict(type='str', aliases=['name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ breakout_map=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['breakout_port_group']],
+ ['state', 'present', ['breakout_port_group']],
+ ],
+ )
+
+ breakout_port_group = module.params.get('breakout_port_group')
+ description = module.params.get('description')
+ breakout_map = module.params.get('breakout_map')
+ state = module.params.get('state')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='infraBrkoutPortGrp',
+ aci_rn='infra/funcprof/brkoutportgrp-{0}'.format(breakout_port_group),
+ module_object=breakout_port_group,
+ target_filter={'name': breakout_port_group},
+ ),
+ child_classes=[],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraBrkoutPortGrp',
+ class_config=dict(
+ name=breakout_port_group,
+ descr=description,
+ brkoutMap=breakout_map,
+ ),
+ )
+
+ aci.get_diff(aci_class='infraBrkoutPortGrp')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py
new file mode 100644
index 00000000..001e6e97
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_policy_group.py
@@ -0,0 +1,580 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_leaf_policy_group
+short_description: Manage fabric interface policy leaf policy groups (infra:AccBndlGrp, infra:AccPortGrp)
+description:
+- Manage fabric interface policy leaf policy groups on Cisco ACI fabrics.
+options:
+ policy_group:
+ description:
+ - Name of the leaf policy group to be added/deleted.
+ type: str
+ aliases: [ name, policy_group_name ]
+ description:
+ description:
+ - Description for the leaf policy group to be created.
+ type: str
+ aliases: [ descr ]
+ lag_type:
+ description:
+ - Selector for the type of leaf policy group we want to create.
+ - C(leaf) for Leaf Access Port Policy Group
+ - C(link) for Port Channel (PC)
+ - C(node) for Virtual Port Channel (VPC)
+ type: str
+ required: yes
+ choices: [ leaf, link, node ]
+ aliases: [ lag_type_name ]
+ link_level_policy:
+ description:
+ - Choice of link_level_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ link_level_policy_name ]
+ cdp_policy:
+ description:
+ - Choice of cdp_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ cdp_policy_name ]
+ mcp_policy:
+ description:
+ - Choice of mcp_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ mcp_policy_name ]
+ lldp_policy:
+ description:
+ - Choice of lldp_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ lldp_policy_name ]
+ stp_interface_policy:
+ description:
+ - Choice of stp_interface_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ stp_interface_policy_name ]
+ egress_data_plane_policing_policy:
+ description:
+ - Choice of egress_data_plane_policing_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ egress_data_plane_policing_policy_name ]
+ ingress_data_plane_policing_policy:
+ description:
+ - Choice of ingress_data_plane_policing_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ ingress_data_plane_policing_policy_name ]
+ priority_flow_control_policy:
+ description:
+ - Choice of priority_flow_control_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ priority_flow_control_policy_name ]
+ fibre_channel_interface_policy:
+ description:
+ - Choice of fibre_channel_interface_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ fibre_channel_interface_policy_name ]
+ slow_drain_policy:
+ description:
+ - Choice of slow_drain_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ slow_drain_policy_name ]
+ port_channel_policy:
+ description:
+ - Choice of port_channel_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ port_channel_policy_name ]
+ monitoring_policy:
+ description:
+ - Choice of monitoring_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ monitoring_policy_name ]
+ storm_control_interface_policy:
+ description:
+ - Choice of storm_control_interface_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ storm_control_interface_policy_name ]
+ l2_interface_policy:
+ description:
+ - Choice of l2_interface_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ l2_interface_policy_name ]
+ port_security_policy:
+ description:
+ - Choice of port_security_policy to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ port_security_policy_name ]
+ aep:
+ description:
+ - Choice of attached_entity_profile (AEP) to be used as part of the leaf policy group to be created.
+ type: str
+ aliases: [ aep_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- When using the module please select the appropriate link_aggregation_type (lag_type).
+ C(link) for Port Channel(PC), C(node) for Virtual Port Channel(VPC) and C(leaf) for Leaf Access Port Policy Group.
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(infra:AccBndlGrp) and B(infra:AccPortGrp).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+'''
+
+EXAMPLES = r'''
+- name: Create a Port Channel (PC) Interface Policy Group
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ lag_type: link
+ policy_group: policygroupname
+ description: policygroupname description
+ link_level_policy: whateverlinklevelpolicy
+ cdp_policy: whatevercdppolicy
+ lldp_policy: whateverlldppolicy
+ port_channel_policy: whateverlacppolicy
+ state: present
+ delegate_to: localhost
+
+- name: Create a Virtual Port Channel (VPC) Interface Policy Group
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ lag_type: node
+ policy_group: policygroupname
+ link_level_policy: whateverlinklevelpolicy
+ cdp_policy: whatevercdppolicy
+ lldp_policy: whateverlldppolicy
+ port_channel_policy: whateverlacppolicy
+ state: present
+ delegate_to: localhost
+
+- name: Create a Leaf Access Port Policy Group
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ lag_type: leaf
+ policy_group: policygroupname
+ link_level_policy: whateverlinklevelpolicy
+ cdp_policy: whatevercdppolicy
+ lldp_policy: whateverlldppolicy
+ state: present
+ delegate_to: localhost
+
+- name: Query all Leaf Access Port Policy Groups of type link
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ lag_type: link
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a specific Lead Access Port Policy Group
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ lag_type: leaf
+ policy_group: policygroupname
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Delete an Interface policy Leaf Policy Group
+ cisco.aci.aci_interface_policy_leaf_policy_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ lag_type: leaf
+ policy_group: policygroupname
+ state: absent
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ # NOTE: Since this module needs to include both infra:AccBndlGrp (for PC and VPC) and infra:AccPortGrp (for leaf access port policy group):
+ # NOTE: I'll allow the user to make the choice here (link(PC), node(VPC), leaf(leaf-access port policy group))
+ lag_type=dict(type='str', required=True, aliases=['lag_type_name'], choices=['leaf', 'link', 'node']),
+ policy_group=dict(type='str', aliases=['name', 'policy_group_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ link_level_policy=dict(type='str', aliases=['link_level_policy_name']),
+ cdp_policy=dict(type='str', aliases=['cdp_policy_name']),
+ mcp_policy=dict(type='str', aliases=['mcp_policy_name']),
+ lldp_policy=dict(type='str', aliases=['lldp_policy_name']),
+ stp_interface_policy=dict(type='str', aliases=['stp_interface_policy_name']),
+ egress_data_plane_policing_policy=dict(type='str', aliases=['egress_data_plane_policing_policy_name']),
+ ingress_data_plane_policing_policy=dict(type='str', aliases=['ingress_data_plane_policing_policy_name']),
+ priority_flow_control_policy=dict(type='str', aliases=['priority_flow_control_policy_name']),
+ fibre_channel_interface_policy=dict(type='str', aliases=['fibre_channel_interface_policy_name']),
+ slow_drain_policy=dict(type='str', aliases=['slow_drain_policy_name']),
+ port_channel_policy=dict(type='str', aliases=['port_channel_policy_name']),
+ monitoring_policy=dict(type='str', aliases=['monitoring_policy_name']),
+ storm_control_interface_policy=dict(type='str', aliases=['storm_control_interface_policy_name']),
+ l2_interface_policy=dict(type='str', aliases=['l2_interface_policy_name']),
+ port_security_policy=dict(type='str', aliases=['port_security_policy_name']),
+ aep=dict(type='str', aliases=['aep_name']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['policy_group']],
+ ['state', 'present', ['policy_group']],
+ ],
+ )
+
+ policy_group = module.params.get('policy_group')
+ description = module.params.get('description')
+ lag_type = module.params.get('lag_type')
+ link_level_policy = module.params.get('link_level_policy')
+ cdp_policy = module.params.get('cdp_policy')
+ mcp_policy = module.params.get('mcp_policy')
+ lldp_policy = module.params.get('lldp_policy')
+ stp_interface_policy = module.params.get('stp_interface_policy')
+ egress_data_plane_policing_policy = module.params.get('egress_data_plane_policing_policy')
+ ingress_data_plane_policing_policy = module.params.get('ingress_data_plane_policing_policy')
+ priority_flow_control_policy = module.params.get('priority_flow_control_policy')
+ fibre_channel_interface_policy = module.params.get('fibre_channel_interface_policy')
+ slow_drain_policy = module.params.get('slow_drain_policy')
+ port_channel_policy = module.params.get('port_channel_policy')
+ monitoring_policy = module.params.get('monitoring_policy')
+ storm_control_interface_policy = module.params.get('storm_control_interface_policy')
+ l2_interface_policy = module.params.get('l2_interface_policy')
+ port_security_policy = module.params.get('port_security_policy')
+ aep = module.params.get('aep')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ if lag_type == 'leaf' and port_channel_policy is not None:
+ aci.fail_json('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).')
+
+ if lag_type == 'leaf':
+ aci_class_name = 'infraAccPortGrp'
+ dn_name = 'accportgrp'
+ class_config_dict = dict(
+ name=policy_group,
+ descr=description,
+ nameAlias=name_alias,
+ )
+ # Reset for target_filter
+ lag_type = None
+ elif lag_type in ('link', 'node'):
+ aci_class_name = 'infraAccBndlGrp'
+ dn_name = 'accbundle'
+ class_config_dict = dict(
+ name=policy_group,
+ descr=description,
+ lagT=lag_type,
+ nameAlias=name_alias,
+ )
+
+ child_configs = [
+ dict(
+ infraRsCdpIfPol=dict(
+ attributes=dict(
+ tnCdpIfPolName=cdp_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsFcIfPol=dict(
+ attributes=dict(
+ tnFcIfPolName=fibre_channel_interface_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsHIfPol=dict(
+ attributes=dict(
+ tnFabricHIfPolName=link_level_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsL2IfPol=dict(
+ attributes=dict(
+ tnL2IfPolName=l2_interface_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsL2PortSecurityPol=dict(
+ attributes=dict(
+ tnL2PortSecurityPolName=port_security_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsLacpPol=dict(
+ attributes=dict(
+ tnLacpLagPolName=port_channel_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsLldpIfPol=dict(
+ attributes=dict(
+ tnLldpIfPolName=lldp_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsMcpIfPol=dict(
+ attributes=dict(
+ tnMcpIfPolName=mcp_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsMonIfInfraPol=dict(
+ attributes=dict(
+ tnMonInfraPolName=monitoring_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsQosEgressDppIfPol=dict(
+ attributes=dict(
+ tnQosDppPolName=egress_data_plane_policing_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsQosIngressDppIfPol=dict(
+ attributes=dict(
+ tnQosDppPolName=ingress_data_plane_policing_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsQosPfcIfPol=dict(
+ attributes=dict(
+ tnQosPfcIfPolName=priority_flow_control_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsQosSdIfPol=dict(
+ attributes=dict(
+ tnQosSdIfPolName=slow_drain_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsStormctrlIfPol=dict(
+ attributes=dict(
+ tnStormctrlIfPolName=storm_control_interface_policy,
+ ),
+ ),
+ ),
+ dict(
+ infraRsStpIfPol=dict(
+ attributes=dict(
+ tnStpIfPolName=stp_interface_policy,
+ ),
+ ),
+ ),
+ ]
+
+ # Add infraRsattEntP binding only when aep was defined
+ if aep is not None:
+ child_configs.append(dict(
+ infraRsAttEntP=dict(
+ attributes=dict(
+ tDn='uni/infra/attentp-{0}'.format(aep),
+ ),
+ ),
+ ))
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class=aci_class_name,
+ aci_rn='infra/funcprof/{0}-{1}'.format(dn_name, policy_group),
+ module_object=policy_group,
+ target_filter={'name': policy_group, 'lagT': lag_type},
+ ),
+ child_classes=[
+ 'infraRsAttEntP',
+ 'infraRsCdpIfPol',
+ 'infraRsFcIfPol',
+ 'infraRsHIfPol',
+ 'infraRsL2IfPol',
+ 'infraRsL2PortSecurityPol',
+ 'infraRsLacpPol',
+ 'infraRsLldpIfPol',
+ 'infraRsMcpIfPol',
+ 'infraRsMonIfInfraPol',
+ 'infraRsQosEgressDppIfPol',
+ 'infraRsQosIngressDppIfPol',
+ 'infraRsQosPfcIfPol',
+ 'infraRsQosSdIfPol',
+ 'infraRsStormctrlIfPol',
+ 'infraRsStpIfPol',
+ ],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=aci_class_name,
+ class_config=class_config_dict,
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class=aci_class_name)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_profile.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_profile.py
new file mode 100644
index 00000000..468ccbc8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_leaf_profile.py
@@ -0,0 +1,313 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Bruno Calogero <brunocalogero@hotmail.com>
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_leaf_profile
+short_description: Manage fabric interface policy leaf profiles (infra:AccPortP)
+description:
+- Manage fabric interface policy leaf profiles on Cisco ACI fabrics.
+options:
+ interface_profile:
+ description:
+ - The name of the Fabric access policy leaf interface profile.
+ type: str
+ aliases: [ name, leaf_interface_profile_name, leaf_interface_profile, interface_profile_name ]
+ description:
+ description:
+ - Description for the Fabric access policy leaf interface profile.
+ type: str
+ aliases: [ descr ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ type:
+ description:
+ - The type of profile to be created.
+ type: str
+ choices: [ fex, leaf ]
+ default: leaf
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(infra:AccPortP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Add a new leaf_interface_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ description: leafintprfname description
+ state: present
+ delegate_to: localhost
+
+- name: Add a new leaf_interface_profile of type fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname_fex
+ type: fex
+ description: leafintprfname description
+ state: present
+ delegate_to: localhost
+
+- name: Remove a leaf_interface_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ state: absent
+ delegate_to: localhost
+
+- name: Remove a leaf_interface_profile of type fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname_fex
+ type: fex
+ state: absent
+ delegate_to: localhost
+
+- name: Query a leaf_interface_profile
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a leaf_interface_profile of type fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ interface_profile: leafintprfname_fex
+ type: fex
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all leaf_interface_profiles
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+
+- name: Query all leaf_interface_profiles of type fex
+ cisco.aci.aci_interface_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ type: fex
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ interface_profile=dict(type='str', aliases=['name', 'leaf_interface_profile_name', 'leaf_interface_profile', 'interface_profile_name']),
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ type=dict(type='str', default='leaf', choices=['fex', 'leaf']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['interface_profile']],
+ ['state', 'present', ['interface_profile']],
+ ],
+ )
+
+ interface_profile = module.params.get('interface_profile')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+ type_profile = module.params.get('type')
+
+ aci = ACIModule(module)
+ aci_class = 'infraAccPortP'
+ aci_rn = 'accportprof'
+ if type_profile == 'fex':
+ aci_class = 'infraFexP'
+ aci_rn = 'fexprof'
+ aci.construct_url(
+ root_class=dict(
+ aci_class=aci_class,
+ aci_rn='infra/' + aci_rn + '-{0}'.format(interface_profile),
+ module_object=interface_profile,
+ target_filter={'name': interface_profile},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=aci_class,
+ class_config=dict(
+ name=interface_profile,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class=aci_class)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py
new file mode 100644
index 00000000..c6e792f7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_link_level.py
@@ -0,0 +1,292 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2019, Vasily Prokopov (@vasilyprokopov)
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_link_level
+short_description: Manage Link Level interface policies (fabric:HIfPol)
+description:
+- The link level interface policy specifies the layer 1 parameters of switch interfaces.
+options:
+ link_level_policy:
+ description:
+ - The name of the Link Level interface policy.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description of the Link Level interface policy.
+ type: str
+ aliases: [ descr ]
+ auto_negotiation:
+ description:
+ - Auto-negotiation enables devices to automatically exchange information over a link about speed and duplex abilities.
+ - The APIC defaults to C(on) when unset during creation.
+ type: bool
+ default: true
+ speed:
+ description:
+ - Determines the interface policy administrative port speed.
+ - The APIC defaults to C(inherit) when unset during creation.
+ type: str
+ choices: [ 100M, 1G, 10G, 25G, 40G, 50G, 100G, 200G, 400G, inherit ]
+ default: inherit
+ link_debounce_interval:
+ description:
+ - Enables the debounce timer for physical interface ports and sets it for a specified amount of time in milliseconds.
+ - The APIC defaults to C(100) when unset during creation.
+ type: int
+ default: 100
+ forwarding_error_correction:
+ description:
+ - Determines the forwarding error correction (FEC) mode.
+ - The APIC defaults to C(inherit) when unset during creation.
+ type: str
+ choices: [ inherit, kp-fec, cl91-rs-fec, cl74-fc-fec, disable-fec, ieee-rs-fec, cons16-rs-fec ]
+ default: inherit
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment: cisco.aci.aci
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fabric:HIfPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Vasily Prokopov (@vasilyprokopov)
+'''
+
+EXAMPLES = r'''
+- name: Add a Link Level Policy
+ aci_interface_policy_link_level:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ link_level_policy: link_level_policy_test
+ description: via Ansible
+ auto_negotiation: on
+ speed: 100M
+ link_debounce_interval: 100
+ forwarding_error_correction: cl91-rs-fec
+ state: present
+ delegate_to: localhost
+
+- name: Remove a Link Level Policy
+ aci_interface_policy_link_level:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ link_level_policy: ansible_test
+ state: absent
+
+- name: Query a Link Level Policy
+ aci_interface_policy_link_level:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ link_level_policy: link_level_policy_test
+ state: query
+ delegate_to: localhost
+
+- name: Query all Link Level Policies
+ aci_interface_policy_link_level:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ link_level_policy=dict(type='str', aliases=['name']),
+ description=dict(type='str', aliases=['descr']),
+ auto_negotiation=dict(type='bool', default='true'),
+ speed=dict(type='str', default='inherit', choices=['100M', '1G', '10G', '25G', '40G', '50G', '100G', '200G', '400G', 'inherit']),
+ link_debounce_interval=dict(type='int', default='100'),
+ forwarding_error_correction=dict(type='str', default='inherit',
+ choices=['inherit', 'kp-fec', 'cl91-rs-fec', 'cl74-fc-fec', 'disable-fec', 'ieee-rs-fec', 'cons16-rs-fec']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['link_level_policy']],
+ ['state', 'present', ['link_level_policy']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ link_level_policy = module.params['link_level_policy']
+ description = module.params['description']
+ auto_negotiation = aci.boolean(module.params['auto_negotiation'], 'on', 'off')
+ speed = module.params['speed']
+ link_debounce_interval = module.params['link_debounce_interval']
+ if link_debounce_interval is not None and link_debounce_interval not in range(0, 5001):
+ module.fail_json(msg='The "link_debounce_interval" must be a value between 0 and 5000')
+ forwarding_error_correction = module.params['forwarding_error_correction']
+ state = module.params['state']
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fabricHIfPol',
+ aci_rn='infra/hintfpol-{0}'.format(link_level_policy),
+ module_object=link_level_policy,
+ target_filter={'name': link_level_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fabricHIfPol',
+ class_config=dict(
+ name=link_level_policy,
+ descr=description,
+ autoNeg=auto_negotiation,
+ speed=speed,
+ linkDebounce=link_debounce_interval,
+ fecMode=forwarding_error_correction,
+ ),
+ )
+
+ aci.get_diff(aci_class='fabricHIfPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_lldp.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_lldp.py
new file mode 100644
index 00000000..a1964733
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_lldp.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_lldp
+short_description: Manage LLDP interface policies (lldp:IfPol)
+description:
+- Manage LLDP interface policies on Cisco ACI fabrics.
+options:
+ lldp_policy:
+ description:
+ - The LLDP interface policy name.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description for the LLDP interface policy name.
+ type: str
+ aliases: [ descr ]
+ receive_state:
+ description:
+ - Enable or disable Receive state.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ transmit_state:
+ description:
+ - Enable or Disable Transmit state.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(lldp:IfPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: Add a LLDP interface policy
+ cisco.aci.aci_interface_policy_lldp:
+ host: '{{ hostname }}'
+ username: '{{ username }}'
+ password: '{{ password }}'
+ lldp_policy: '{{ lldp_policy }}'
+ description: '{{ description }}'
+ receive_state: '{{ receive_state }}'
+ transmit_state: '{{ transmit_state }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ lldp_policy=dict(type='str', aliases=['name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ receive_state=dict(type='bool'),
+ transmit_state=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['lldp_policy']],
+ ['state', 'present', ['lldp_policy']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ lldp_policy = module.params.get('lldp_policy')
+ description = module.params.get('description')
+ receive_state = aci.boolean(module.params.get('receive_state'), 'enabled', 'disabled')
+ transmit_state = aci.boolean(module.params.get('transmit_state'), 'enabled', 'disabled')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='lldpIfPol',
+ aci_rn='infra/lldpIfP-{0}'.format(lldp_policy),
+ module_object=lldp_policy,
+ target_filter={'name': lldp_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='lldpIfPol',
+ class_config=dict(
+ name=lldp_policy,
+ descr=description,
+ adminRxSt=receive_state,
+ adminTxSt=transmit_state,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='lldpIfPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_mcp.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_mcp.py
new file mode 100644
index 00000000..97a1360a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_mcp.py
@@ -0,0 +1,239 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_mcp
+short_description: Manage MCP interface policies (mcp:IfPol)
+description:
+- Manage MCP interface policies on Cisco ACI fabrics.
+options:
+ mcp:
+ description:
+ - The name of the MCP interface.
+ type: str
+ aliases: [ mcp_interface, name ]
+ description:
+ description:
+ - The description for the MCP interface.
+ type: str
+ aliases: [ descr ]
+ admin_state:
+ description:
+ - Enable or disable admin state.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(mcp:IfPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: Add a MCP interface policy
+ cisco.aci.aci_interface_policy_mcp:
+ host: '{{ hostname }}'
+ username: '{{ username }}'
+ password: '{{ password }}'
+ mcp: '{{ mcp }}'
+ description: '{{ descr }}'
+ admin_state: '{{ admin_state }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ mcp=dict(type='str', aliases=['mcp_interface', 'name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ admin_state=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['mcp']],
+ ['state', 'present', ['mcp']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ mcp = module.params.get('mcp')
+ description = module.params.get('description')
+ admin_state = aci.boolean(module.params.get('admin_state'), 'enabled', 'disabled')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='mcpIfPol',
+ aci_rn='infra/mcpIfP-{0}'.format(mcp),
+ module_object=mcp,
+ target_filter={'name': mcp},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='mcpIfPol',
+ class_config=dict(
+ name=mcp,
+ descr=description,
+ adminSt=admin_state,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='mcpIfPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_ospf.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_ospf.py
new file mode 100644
index 00000000..ff08e7a1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_ospf.py
@@ -0,0 +1,405 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_ospf
+short_description: Manage OSPF interface policies (ospf:IfPol)
+description:
+- Manage OSPF interface policies on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - The name of the Tenant the OSPF interface policy should belong to.
+ type: str
+ aliases: [ tenant_name ]
+ ospf:
+ description:
+ - The OSPF interface policy name.
+ - This name can be between 1 and 64 alphanumeric characters.
+ - Note that you cannot change this name after the object has been saved.
+ type: str
+ aliases: [ ospf_interface, name ]
+ description:
+ description:
+ - The description for the OSPF interface.
+ type: str
+ aliases: [ descr ]
+ network_type:
+ description:
+ - The OSPF interface policy network type.
+ - OSPF supports broadcast and point-to-point.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ bcast, p2p ]
+ cost:
+ description:
+ - The OSPF cost of the interface.
+ - The cost (also called metric) of an interface in OSPF is an indication of
+ the overhead required to send packets across a certain interface. The
+ cost of an interface is inversely proportional to the bandwidth of that
+ interface. A higher bandwidth indicates a lower cost. There is more
+ overhead (higher cost) and time delays involved in crossing a 56k serial
+ line than crossing a 10M ethernet line. The formula used to calculate the
+ cost is C(cost= 10000 0000/bandwith in bps) For example, it will cost
+ 10 EXP8/10 EXP7 = 10 to cross a 10M Ethernet line and will cost
+ 10 EXP8/1544000 = 64 to cross a T1 line.
+ - By default, the cost of an interface is calculated based on the bandwidth;
+ you can force the cost of an interface with the ip ospf cost value
+ interface subconfiguration mode command.
+ - Accepted values range between C(1) and C(450).
+ - The APIC defaults to C(0) when unset during creation.
+ type: int
+ controls:
+ description:
+ - The interface policy controls.
+ - 'This is a list of one or more of the following controls:'
+ - C(advert-subnet) -- Advertise IP subnet instead of a host mask in the router LSA.
+ - C(bfd) -- Bidirectional Forwarding Detection
+ - C(mtu-ignore) -- Disables MTU mismatch detection on an interface.
+ - C(passive) -- The interface does not participate in the OSPF protocol and
+ will not establish adjacencies or send routing updates. However the
+ interface is announced as part of the routing network.
+ type: list
+ elements: str
+ choices: [ advert-subnet, bfd, mtu-ignore, passive ]
+ dead_interval:
+ description:
+ - The interval between hello packets from a neighbor before the router
+ declares the neighbor as down.
+ - This value must be the same for all networking devices on a specific network.
+ - Specifying a smaller dead interval (seconds) will give faster detection
+ of a neighbor being down and improve convergence, but might cause more
+ routing instability.
+ - Accepted values range between C(1) and C(65535).
+ - The APIC defaults to C(40) when unset during creation.
+ type: int
+ hello_interval:
+ description:
+ - The interval between hello packets that OSPF sends on the interface.
+ - Note that the smaller the hello interval, the faster topological changes will be detected, but more routing traffic will ensue.
+ - This value must be the same for all routers and access servers on a specific network.
+ - Accepted values range between C(1) and C(65535).
+ - The APIC defaults to C(10) when unset during creation.
+ type: int
+ prefix_suppression:
+ description:
+ - Whether prefix suppressions is enabled or disabled.
+ - The APIC defaults to C(inherit) when unset during creation.
+ type: bool
+ priority:
+ description:
+ - The priority for the OSPF interface profile.
+ - Accepted values ranges between C(0) and C(255).
+ - The APIC defaults to C(1) when unset during creation.
+ type: int
+ retransmit_interval:
+ description:
+ - The interval between LSA retransmissions.
+ - The retransmit interval occurs while the router is waiting for an acknowledgement from the neighbor router that it received the LSA.
+ - If no acknowledgment is received at the end of the interval, then the LSA is resent.
+ - Accepted values range between C(1) and C(65535).
+ - The APIC defaults to C(5) when unset during creation.
+ type: int
+ transmit_delay:
+ description:
+ - The delay time needed to send an LSA update packet.
+ - OSPF increments the LSA age time by the transmit delay amount before transmitting the LSA update.
+ - You should take into account the transmission and propagation delays for the interface when you set this value.
+ - Accepted values range between C(1) and C(450).
+ - The APIC defaults to C(1) when unset during creation.
+ type: int
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(ospf:IfPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Ensure ospf interface policy exists
+ cisco.aci.aci_interface_policy_ospf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ospf: ospf1
+ state: present
+ delegate_to: localhost
+
+- name: Ensure ospf interface policy does not exist
+ cisco.aci.aci_interface_policy_ospf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ospf: ospf1
+ state: present
+ delegate_to: localhost
+
+- name: Query an ospf interface policy
+ cisco.aci.aci_interface_policy_ospf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ ospf: ospf1
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all ospf interface policies in tenant production
+ cisco.aci.aci_interface_policy_ospf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ ospf=dict(type='str', aliases=['ospf_interface', 'name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ network_type=dict(type='str', choices=['bcast', 'p2p']),
+ cost=dict(type='int'),
+ controls=dict(type='list', elements='str', choices=['advert-subnet', 'bfd', 'mtu-ignore', 'passive']),
+ dead_interval=dict(type='int'),
+ hello_interval=dict(type='int'),
+ prefix_suppression=dict(type='bool'),
+ priority=dict(type='int'),
+ retransmit_interval=dict(type='int'),
+ transmit_delay=dict(type='int'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['ospf', 'tenant']],
+ ['state', 'present', ['ospf', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ tenant = module.params.get('tenant')
+ ospf = module.params.get('ospf')
+ description = module.params.get('description')
+ name_alias = module.params.get('name_alias')
+
+ if module.params.get('controls') is None:
+ controls = None
+ else:
+ controls = ','.join(module.params.get('controls'))
+
+ cost = module.params.get('cost')
+ if cost is not None and cost not in range(1, 451):
+ module.fail_json(msg="Parameter 'cost' is only valid in range between 1 and 450.")
+
+ dead_interval = module.params.get('dead_interval')
+ if dead_interval is not None and dead_interval not in range(1, 65536):
+ module.fail_json(msg="Parameter 'dead_interval' is only valid in range between 1 and 65536.")
+
+ hello_interval = module.params.get('hello_interval')
+ if hello_interval is not None and hello_interval not in range(1, 65536):
+ module.fail_json(msg="Parameter 'hello_interval' is only valid in range between 1 and 65536.")
+
+ network_type = module.params.get('network_type')
+ prefix_suppression = aci.boolean(module.params.get('prefix_suppression'), 'enabled', 'disabled')
+ priority = module.params.get('priority')
+ if priority is not None and priority not in range(0, 256):
+ module.fail_json(msg="Parameter 'priority' is only valid in range between 1 and 255.")
+
+ retransmit_interval = module.params.get('retransmit_interval')
+ if retransmit_interval is not None and retransmit_interval not in range(1, 65536):
+ module.fail_json(msg="Parameter 'retransmit_interval' is only valid in range between 1 and 65536.")
+
+ transmit_delay = module.params.get('transmit_delay')
+ if transmit_delay is not None and transmit_delay not in range(1, 451):
+ module.fail_json(msg="Parameter 'transmit_delay' is only valid in range between 1 and 450.")
+
+ state = module.params.get('state')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='ospfIfPol',
+ aci_rn='tn-{0}/ospfIfPol-{1}'.format(tenant, ospf),
+ module_object=ospf,
+ target_filter={'name': ospf},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='ospfIfPol',
+ class_config=dict(
+ name=ospf,
+ descr=description,
+ cost=cost,
+ ctrl=controls,
+ deadIntvl=dead_interval,
+ helloIntvl=hello_interval,
+ nwT=network_type,
+ pfxSuppress=prefix_suppression,
+ prio=priority,
+ rexmitIntvl=retransmit_interval,
+ xmitDelay=transmit_delay,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='ospfIfPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_channel.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_channel.py
new file mode 100644
index 00000000..94e2fd74
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_channel.py
@@ -0,0 +1,322 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_port_channel
+short_description: Manage port channel interface policies (lacp:LagPol)
+description:
+- Manage port channel interface policies on Cisco ACI fabrics.
+options:
+ port_channel:
+ description:
+ - Name of the port channel.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description for the port channel.
+ type: str
+ aliases: [ descr ]
+ max_links:
+ description:
+ - Maximum links.
+ - Accepted values range between 1 and 16.
+ - The APIC defaults to C(16) when unset during creation.
+ type: int
+ min_links:
+ description:
+ - Minimum links.
+ - Accepted values range between 1 and 16.
+ - The APIC defaults to C(1) when unset during creation.
+ type: int
+ mode:
+ description:
+ - Port channel interface policy mode.
+ - Determines the LACP method to use for forming port-channels.
+ - The APIC defaults to C(off) when unset during creation.
+ type: str
+ choices: [ active, mac-pin, mac-pin-nicload, 'off', passive ]
+ fast_select:
+ description:
+ - Determines if Fast Select is enabled for Hot Standby Ports.
+ - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
+ left undefined or set to false will not exist after the task is ran.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ graceful_convergence:
+ description:
+ - Determines if Graceful Convergence is enabled.
+ - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
+ left undefined or set to false will not exist after the task is ran.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ load_defer:
+ description:
+ - Determines if Load Defer is enabled.
+ - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
+ left undefined or set to false will not exist after the task is ran.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ suspend_individual:
+ description:
+ - Determines if Suspend Individual is enabled.
+ - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
+ left undefined or set to false will not exist after the task is ran.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ symmetric_hash:
+ description:
+ - Determines if Symmetric Hashing is enabled.
+ - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties
+ left undefined or set to false will not exist after the task is ran.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(lacp:LagPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: Add a port channel interface policy
+ cisco.aci.aci_interface_policy_port_channel:
+ host: '{{ inventory_hostname }}'
+ username: '{{ username }}'
+ password: '{{ password }}'
+ port_channel: '{{ port_channel }}'
+ description: '{{ description }}'
+ min_links: '{{ min_links }}'
+ max_links: '{{ max_links }}'
+ mode: '{{ mode }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ port_channel=dict(type='str', aliases=['name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ min_links=dict(type='int'),
+ max_links=dict(type='int'),
+ mode=dict(type='str', choices=['active', 'mac-pin', 'mac-pin-nicload', 'off', 'passive']),
+ fast_select=dict(type='bool'),
+ graceful_convergence=dict(type='bool'),
+ load_defer=dict(type='bool'),
+ suspend_individual=dict(type='bool'),
+ symmetric_hash=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['port_channel']],
+ ['state', 'present', ['port_channel']],
+ ],
+ )
+
+ port_channel = module.params.get('port_channel')
+ description = module.params.get('description')
+ min_links = module.params.get('min_links')
+ if min_links is not None and min_links not in range(1, 17):
+ module.fail_json(msg='The "min_links" must be a value between 1 and 16')
+ max_links = module.params.get('max_links')
+ if max_links is not None and max_links not in range(1, 17):
+ module.fail_json(msg='The "max_links" must be a value between 1 and 16')
+ mode = module.params.get('mode')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ # Build ctrl value for request
+ ctrl = []
+ if module.params.get('fast_select') is True:
+ ctrl.append('fast-sel-hot-stdby')
+ if module.params.get('graceful_convergence') is True:
+ ctrl.append('graceful-conv')
+ if module.params.get('load_defer') is True:
+ ctrl.append('load-defer')
+ if module.params.get('suspend_individual') is True:
+ ctrl.append('susp-individual')
+ if module.params.get('symmetric_hash') is True:
+ ctrl.append('symmetric-hash')
+ if not ctrl:
+ ctrl = None
+ else:
+ ctrl = ",".join(ctrl)
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='lacpLagPol',
+ aci_rn='infra/lacplagp-{0}'.format(port_channel),
+ module_object=port_channel,
+ target_filter={'name': port_channel},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='lacpLagPol',
+ class_config=dict(
+ name=port_channel,
+ ctrl=ctrl,
+ descr=description,
+ minLinks=min_links,
+ maxLinks=max_links,
+ mode=mode,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='lacpLagPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_security.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_security.py
new file mode 100644
index 00000000..557fd2f4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_policy_port_security.py
@@ -0,0 +1,253 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_policy_port_security
+short_description: Manage port security (l2:PortSecurityPol)
+description:
+- Manage port security on Cisco ACI fabrics.
+options:
+ port_security:
+ description:
+ - The name of the port security.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description for the contract.
+ type: str
+ aliases: [ descr ]
+ max_end_points:
+ description:
+ - Maximum number of end points.
+ - Accepted values range between C(0) and C(12000).
+ - The APIC defaults to C(0) when unset during creation.
+ type: int
+ port_security_timeout:
+ description:
+ - The delay time in seconds before MAC learning is re-enabled
+ - Accepted values range between C(60) and C(3600)
+ - The APIC defaults to C(60) when unset during creation
+ type: int
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l2:PortSecurityPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: Add a port security interface policy
+ cisco.aci.aci_interface_policy_port_security:
+ host: '{{ inventory_hostname }}'
+ username: '{{ username }}'
+ password: '{{ password }}'
+ port_security: '{{ port_security }}'
+ description: '{{ descr }}'
+ max_end_points: '{{ max_end_points }}'
+ port_security_timeout: '{{ port_security_timeout }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ port_security=dict(type='str', aliases=['name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ max_end_points=dict(type='int'),
+ port_security_timeout=dict(type='int'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['port_security']],
+ ['state', 'present', ['port_security']],
+ ],
+ )
+
+ port_security = module.params.get('port_security')
+ description = module.params.get('description')
+ max_end_points = module.params.get('max_end_points')
+ port_security_timeout = module.params.get('port_security_timeout')
+ name_alias = module.params.get('name_alias')
+ if max_end_points is not None and max_end_points not in range(12001):
+ module.fail_json(msg='The max_end_points must be between 0 and 12000')
+ if port_security_timeout is not None and port_security_timeout not in range(60, 3601):
+ module.fail_json(msg='The port_security_timeout must be between 60 and 3600')
+ state = module.params.get('state')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='l2PortSecurityPol',
+ aci_rn='infra/portsecurityP-{0}'.format(port_security),
+ module_object=port_security,
+ target_filter={'name': port_security},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='l2PortSecurityPol',
+ class_config=dict(
+ name=port_security,
+ descr=description,
+ maximum=max_end_points,
+ nameAlias=name_alias,
+ timeout=port_security_timeout,
+ ),
+ )
+
+ aci.get_diff(aci_class='l2PortSecurityPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_selector_to_switch_policy_leaf_profile.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_selector_to_switch_policy_leaf_profile.py
new file mode 100644
index 00000000..6921e015
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_interface_selector_to_switch_policy_leaf_profile.py
@@ -0,0 +1,254 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_interface_selector_to_switch_policy_leaf_profile
+short_description: Bind interface selector profiles to switch policy leaf profiles (infra:RsAccPortP)
+description:
+- Bind interface selector profiles to switch policy leaf profiles on Cisco ACI fabrics.
+options:
+ leaf_profile:
+ description:
+ - Name of the Leaf Profile to which we add a Selector.
+ type: str
+ aliases: [ leaf_profile_name ]
+ interface_selector:
+ description:
+ - Name of Interface Profile Selector to be added and associated with the Leaf Profile.
+ type: str
+ aliases: [ name, interface_selector_name, interface_profile_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- This module requires an existing leaf profile, the module M(cisco.aci.aci_switch_policy_leaf_profile) can be used for this.
+seealso:
+- module: cisco.aci.aci_switch_policy_leaf_profile
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(infra:RsAccPortP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+'''
+
+EXAMPLES = r'''
+- name: Associating an interface selector profile to a switch policy leaf profile
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ interface_selector: interface_profile_name
+ state: present
+ delegate_to: localhost
+
+- name: Remove an interface selector profile associated with a switch policy leaf profile
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ interface_selector: interface_profile_name
+ state: absent
+ delegate_to: localhost
+
+- name: Query an interface selector profile associated with a switch policy leaf profile
+ cisco.aci.aci_interface_selector_to_switch_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ interface_selector: interface_profile_name
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ leaf_profile=dict(type='str', aliases=['leaf_profile_name']), # Not required for querying all objects
+ interface_selector=dict(type='str', aliases=['interface_profile_name', 'interface_selector_name', 'name']), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query'])
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['leaf_profile', 'interface_selector']],
+ ['state', 'present', ['leaf_profile', 'interface_selector']]
+ ],
+ )
+
+ leaf_profile = module.params.get('leaf_profile')
+ # WARNING: interface_selector accepts non existing interface_profile names and they appear on APIC gui with a state of "missing-target"
+ interface_selector = module.params.get('interface_selector')
+ state = module.params.get('state')
+
+ # Defining the interface profile tDn for clarity
+ interface_selector_tDn = 'uni/infra/accportprof-{0}'.format(interface_selector)
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='infraNodeP',
+ aci_rn='infra/nprof-{0}'.format(leaf_profile),
+ module_object=leaf_profile,
+ target_filter={'name': leaf_profile},
+ ),
+ subclass_1=dict(
+ aci_class='infraRsAccPortP',
+ aci_rn='rsaccPortP-[{0}]'.format(interface_selector_tDn),
+ module_object=interface_selector,
+ target_filter={'name': interface_selector},
+ )
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraRsAccPortP',
+ class_config=dict(tDn=interface_selector_tDn),
+ )
+
+ aci.get_diff(aci_class='infraRsAccPortP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py
new file mode 100644
index 00000000..5550c715
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out.py
@@ -0,0 +1,320 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Sudhakar Shet Kudtarkar (@kudtarkar1)
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l2out
+short_description: Manage Layer2 Out (L2Out) objects.
+description:
+- Manage Layer2 Out configuration on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ l2out:
+ description:
+ - The name of outer layer2.
+ type: str
+ aliases: [ 'name' ]
+ description:
+ description:
+ - Description for the L2Out.
+ type: str
+ bd:
+ description:
+ - Name of the Bridge domain which is associted with the L2Out.
+ type: str
+ domain:
+ description:
+ - Name of the external L2 Domain that is being associated with L2Out.
+ type: str
+ vlan:
+ description:
+ - The VLAN which is being associated with the L2Out.
+ type: int
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) modules can be used for this.
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fvTenant).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Sudhakar Shet Kudtarkar (@kudtarkar1)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Add a new L2Out
+ cisco.aci.aci_l2out:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l2out: l2out
+ description: via Ansible
+ bd: bd1
+ domain: l2Dom
+ vlan: 3200
+ state: present
+ delegate_to: localhost
+
+- name: Remove an L2Out
+ cisco.aci.aci_l2out:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l2out: l2out
+ state: absent
+ delegate_to: localhost
+
+- name: Query an L2Out
+ cisco.aci.aci_l2out:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l2out: l2out
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all L2Outs in a specific tenant
+ cisco.aci.aci_l2out:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+ current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+ error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+ raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>'
+ sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+ previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+ proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+ filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+ method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+ response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+ status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+ url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+ '''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ bd=dict(type='str'),
+ l2out=dict(type='str', aliases=['name']),
+ domain=dict(type='str'),
+ vlan=dict(type='int'),
+ description=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str'),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['l2out', 'tenant']],
+ ['state', 'present', ['bd', 'l2out', 'tenant', 'domain', 'vlan']],
+ ],
+ )
+
+ bd = module.params.get('bd')
+ l2out = module.params.get('l2out')
+ description = module.params.get('description')
+ domain = module.params.get('domain')
+ vlan = module.params.get('vlan')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+ child_classes = ['l2extRsEBd', 'l2extRsL2DomAtt', 'l2extLNodeP']
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l2extOut',
+ aci_rn='l2out-{0}'.format(l2out),
+ module_object=l2out,
+ target_filter={'name': l2out},
+ ),
+ child_classes=child_classes,
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ child_configs = [
+ dict(
+ l2extRsL2DomAtt=dict(
+ attributes=dict(
+ tDn='uni/l2dom-{0}'.format(domain)
+ )
+ )
+ ),
+ dict(
+ l2extRsEBd=dict(
+ attributes=dict(
+ tnFvBDName=bd, encap='vlan-{0}'.format(vlan)
+ )
+ )
+ )
+ ]
+
+ aci.payload(
+ aci_class='l2extOut',
+ class_config=dict(
+ name=l2out,
+ descr=description,
+ dn='uni/tn-{0}/l2out-{1}'.format(tenant, l2out),
+ nameAlias=name_alias
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='l2extOut')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py
new file mode 100644
index 00000000..8111e2b2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l2out_extepg.py
@@ -0,0 +1,310 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Sudhakar Shet Kudtarkar (@kudtarkar1)
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'}
+
+
+DOCUMENTATION = r'''
+---
+module: aci_l2out_extepg
+short_description: Manage External Network Instance (L2Out External EPG) objects (l2extInstP).
+description:
+- Manage External Network Instance (L2Out External EPG) objects (l2extInstP) on ACI fabrics.
+options:
+ tenant:
+ description:
+ - Name of existing tenant.
+ type: str
+ l2out:
+ description:
+ - Name of the l2out.
+ type: str
+ extepg:
+ description:
+ - Name of the external end point group.
+ type: str
+ aliases: [ external_epg, extepg_name, name ]
+ description:
+ description:
+ - Description for the l2out.
+ type: str
+ preferred_group:
+ description:
+ - This depicts whether this External EPG is part of the Preferred Group and can communicate without contracts.
+ - This is convenient for migration scenarios, or when ACI is used for network automation but not for policy.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ qos_class:
+ description:
+ - The bandwidth level for Quality of service.
+ type: str
+ choices: [ level1, level2, level3, level4, level5, level6, Unspecified ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(l2out) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_l2out) modules can be used for this.
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fvtenant) and B(l2extOut).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Sudhakar Shet Kudtarkar (@kudtarkar1)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Add a new L2 external end point group
+ cisco.aci.aci_l2out_extepg:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l2out: l2out
+ extepg: NewExt
+ description: external epg
+ preferred_group: False
+ state: present
+ delegate_to: localhost
+
+- name: Remove an L2 external end point group
+ cisco.aci.aci_l2out_extepg:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l2out: l2out
+ extepg: NewExt
+ state: absent
+ delegate_to: localhost
+
+- name: Query the L2 external end point group
+ cisco.aci.aci_l2out_extepg:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l2out: l2out
+ extepg: NewExt
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all L2 external end point groups in a tenant
+ cisco.aci.aci_l2out_extepg:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+ current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+ error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+ raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>'
+ sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+ previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+ proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+ filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+ method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+ response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+ status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+ url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+ '''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ l2out=dict(type='str'),
+ description=dict(type='str'),
+ extepg=dict(type='str', aliases=['external_epg', 'extepg_name', 'name']),
+ preferred_group=dict(type='bool'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str'),
+ qos_class=dict(type='str', choices=['level1', 'level2', 'level3', 'level4', 'level5', 'level6', 'Unspecified']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['l2out', 'tenant', 'extepg']],
+ ['state', 'present', ['l2out', 'tenant', 'extepg']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ l2out = module.params.get('l2out')
+ description = module.params.get('description')
+ preferred_group = aci.boolean(module.params.get('preferred_group'), 'include', 'exclude')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ extepg = module.params.get('extepg')
+ qos_class = module.params.get('qos_class')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l2extOut',
+ aci_rn='l2out-{0}'.format(l2out),
+ module_object=l2out,
+ target_filter={'name': l2out},
+ ),
+ subclass_2=dict(
+ aci_class='l2extInstP',
+ aci_rn='instP-{0}'.format(extepg),
+ module_object=extepg,
+ target_filter={'name': extepg},
+
+ )
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ config = dict(
+ name=extepg,
+ descr=description,
+ dn='uni/tn-{0}/l2out-{1}/instP-{2}'.format(tenant, l2out, extepg),
+ prefGrMemb=preferred_group
+ )
+ if qos_class:
+ config.update(prio=qos_class)
+ aci.payload(
+ class_config=config,
+ aci_class='l2extInstP',
+ )
+
+ aci.get_diff(aci_class='l2extInstP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py
new file mode 100644
index 00000000..50fee411
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out.py
@@ -0,0 +1,367 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l3out
+short_description: Manage Layer 3 Outside (L3Out) objects (l3ext:Out)
+description:
+- Manage Layer 3 Outside (L3Out) on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ l3out:
+ description:
+ - Name of L3Out being created.
+ type: str
+ aliases: [ l3out_name, name ]
+ vrf:
+ description:
+ - Name of the VRF being associated with the L3Out.
+ type: str
+ aliases: [ vrf_name ]
+ domain:
+ description:
+ - Name of the external L3 domain being associated with the L3Out.
+ type: str
+ aliases: [ ext_routed_domain_name, routed_domain ]
+ dscp:
+ description:
+ - The target Differentiated Service (DSCP) value.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ AF11, AF12, AF13, AF21, AF22, AF23, AF31, AF32, AF33, AF41, AF42, AF43, CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, EF, VA, unspecified ]
+ aliases: [ target ]
+ route_control:
+ description:
+ - Route Control enforcement direction. The only allowed values are export or import,export.
+ type: list
+ elements: str
+ choices: [ export, import ]
+ aliases: [ route_control_enforcement ]
+ l3protocol:
+ description:
+ - Routing protocol for the L3Out
+ type: list
+ elements: str
+ choices: [ bgp, eigrp, ospf, pim, static ]
+ asn:
+ description:
+ - The AS number for the L3Out.
+ - Only applicable when using 'eigrp' as the l3protocol
+ type: int
+ aliases: [ as_number ]
+ description:
+ description:
+ - Description for the L3Out.
+ type: str
+ aliases: [ descr ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(domain) and C(vrf) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_domain) and M(cisco.aci.aci_vrf) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_domain
+- module: cisco.aci.aci_vrf
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l3ext:Out).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Rostyslav Davydenko (@rost-d)
+'''
+
+EXAMPLES = r'''
+- name: Add a new L3Out
+ cisco.aci.aci_l3out:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ name: prod_l3out
+ description: L3Out for Production tenant
+ domain: l3dom_prod
+ vrf: prod
+ l3protocol: ospf
+ state: present
+ delegate_to: localhost
+
+- name: Delete L3Out
+ cisco.aci.aci_l3out:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ name: prod_l3out
+ state: absent
+ delegate_to: localhost
+
+- name: Query L3Out information
+ cisco.aci.aci_l3out:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ name: prod_l3out
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ l3out=dict(type='str', aliases=['l3out_name', 'name']), # Not required for querying all objects
+ domain=dict(type='str', aliases=['ext_routed_domain_name', 'routed_domain']),
+ vrf=dict(type='str', aliases=['vrf_name']),
+ description=dict(type='str', aliases=['descr']),
+ route_control=dict(type='list', elements='str', choices=['export', 'import'], aliases=['route_control_enforcement']),
+ dscp=dict(type='str',
+ choices=['AF11', 'AF12', 'AF13', 'AF21', 'AF22', 'AF23', 'AF31', 'AF32', 'AF33', 'AF41', 'AF42',
+ 'AF43', 'CS0', 'CS1', 'CS2', 'CS3', 'CS4', 'CS5', 'CS6', 'CS7', 'EF', 'VA', 'unspecified'],
+ aliases=['target']),
+ l3protocol=dict(type='list', elements='str', choices=['bgp', 'eigrp', 'ospf', 'pim', 'static']),
+ asn=dict(type='int', aliases=['as_number']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['l3out', 'tenant']],
+ ['state', 'present', ['l3out', 'tenant', 'domain', 'vrf']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ l3out = module.params.get('l3out')
+ domain = module.params.get('domain')
+ dscp = module.params.get('dscp')
+ description = module.params.get('description')
+ enforceRtctrl = module.params.get('route_control')
+ vrf = module.params.get('vrf')
+ l3protocol = module.params.get('l3protocol')
+ asn = module.params.get('asn')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ if l3protocol:
+ if 'eigrp' in l3protocol and asn is None:
+ module.fail_json(msg="Parameter 'asn' is required when l3protocol is 'eigrp'")
+ if 'eigrp' not in l3protocol and asn is not None:
+ module.warn("Parameter 'asn' is only applicable when l3protocol is 'eigrp'. The ASN will be ignored")
+
+ enforce_ctrl = ''
+ if enforceRtctrl is not None:
+ if len(enforceRtctrl) == 1 and enforceRtctrl[0] == 'import':
+ aci.fail_json(
+ "The route_control parameter is invalid: allowed options are export or import,export only")
+ elif len(enforceRtctrl) == 1 and enforceRtctrl[0] == 'export':
+ enforce_ctrl = 'export'
+ else:
+ enforce_ctrl = 'export,import'
+ child_classes = ['l3extRsL3DomAtt', 'l3extRsEctx', 'bgpExtP', 'ospfExtP', 'eigrpExtP', 'pimExtP']
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l3extOut',
+ aci_rn='out-{0}'.format(l3out),
+ module_object=l3out,
+ target_filter={'name': l3out},
+ ),
+ child_classes=child_classes,
+ )
+
+ aci.get_existing()
+
+ child_configs = [
+ dict(l3extRsL3DomAtt=dict(attributes=dict(
+ tDn='uni/l3dom-{0}'.format(domain)))),
+ dict(l3extRsEctx=dict(attributes=dict(tnFvCtxName=vrf))),
+ ]
+ if l3protocol is not None:
+ for protocol in l3protocol:
+ if protocol == 'bgp':
+ child_configs.append(
+ dict(bgpExtP=dict(attributes=dict(descr='', nameAlias=''))))
+ elif protocol == 'eigrp':
+ child_configs.append(
+ dict(eigrpExtP=dict(attributes=dict(descr='', nameAlias='', asn=asn))))
+ elif protocol == 'ospf':
+ child_configs.append(
+ dict(ospfExtP=dict(attributes=dict(descr='', nameAlias=''))))
+ elif protocol == 'pim':
+ child_configs.append(
+ dict(pimExtP=dict(attributes=dict(descr='', nameAlias=''))))
+
+ if state == 'present':
+ aci.payload(
+ aci_class='l3extOut',
+ class_config=dict(
+ name=l3out,
+ descr=description,
+ dn='uni/tn-{0}/out-{1}'.format(tenant, l3out),
+ enforceRtctrl=enforce_ctrl,
+ targetDscp=dscp,
+ nameAlias=name_alias,
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='l3extOut')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py
new file mode 100644
index 00000000..bbe4dfa6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg.py
@@ -0,0 +1,309 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l3out_extepg
+short_description: Manage External Network Instance Profile (ExtEpg) objects (l3extInstP:instP)
+description:
+- Manage External Network Instance Profile (ExtEpg) objects (l3extInstP:instP)
+options:
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ l3out:
+ description:
+ - Name of an existing L3Out.
+ type: str
+ aliases: [ l3out_name ]
+ extepg:
+ description:
+ - Name of ExtEpg being created.
+ type: str
+ aliases: [ extepg_name, name ]
+ description:
+ description:
+ - Description for the ExtEpg.
+ type: str
+ aliases: [ descr ]
+ preferred_group:
+ description:
+ - Whether ot not the EPG is part of the Preferred Group and can communicate without contracts.
+ - This is very convenient for migration scenarios, or when ACI is used for network automation but not for policy.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ dscp:
+ description:
+ - The target Differentiated Service (DSCP) value.
+ - The APIC defaults to C(unspecified) when unset during creation.
+ type: str
+ choices: [ AF11, AF12, AF13, AF21, AF22, AF23, AF31, AF32, AF33, AF41, AF42, AF43, CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, EF, VA, unspecified ]
+ aliases: [ target ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(domain) and C(vrf) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_domain) and M(cisco.aci.aci_vrf) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_domain
+- module: cisco.aci.aci_vrf
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l3ext:Out).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Rostyslav Davydenko (@rost-d)
+'''
+
+EXAMPLES = r'''
+- name: Add a new ExtEpg
+ cisco.aci.aci_l3out_extepg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ l3out: prod_l3out
+ name: prod_extepg
+ description: ExtEpg for Production L3Out
+ state: present
+ delegate_to: localhost
+
+- name: Delete ExtEpg
+ cisco.aci.aci_extepg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ l3out: prod_l3out
+ name: prod_extepg
+ state: absent
+ delegate_to: localhost
+
+- name: Query ExtEpg information
+ cisco.aci.aci_l3out_extepg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ l3out: prod_l3out
+ name: prod_extepg
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ l3out=dict(type='str', aliases=['l3out_name']), # Not required for querying all objects
+ extepg=dict(type='str', aliases=['extepg_name', 'name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ preferred_group=dict(type='bool'),
+ dscp=dict(type='str',
+ choices=['AF11', 'AF12', 'AF13', 'AF21', 'AF22', 'AF23', 'AF31', 'AF32', 'AF33', 'AF41', 'AF42',
+ 'AF43', 'CS0', 'CS1', 'CS2', 'CS3', 'CS4', 'CS5', 'CS6', 'CS7', 'EF', 'VA', 'unspecified'],
+ aliases=['target']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'present', ['extepg', 'l3out', 'tenant']],
+ ['state', 'absent', ['extepg', 'l3out', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ tenant = module.params.get('tenant')
+ l3out = module.params.get('l3out')
+ extepg = module.params.get('extepg')
+ description = module.params.get('description')
+ preferred_group = aci.boolean(module.params.get('preferred_group'), 'include', 'exclude')
+ dscp = module.params.get('dscp')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l3extOut',
+ aci_rn='out-{0}'.format(l3out),
+ module_object=l3out,
+ target_filter={'name': l3out},
+ ),
+ subclass_2=dict(
+ aci_class='l3extInstP',
+ aci_rn='instP-{0}'.format(extepg),
+ module_object=extepg,
+ target_filter={'name': extepg},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='l3extInstP',
+ class_config=dict(
+ name=extepg,
+ descr=description,
+ prefGrMemb=preferred_group,
+ targetDscp=dscp,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='l3extInstP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py
new file mode 100644
index 00000000..9bc94fe7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extepg_to_contract.py
@@ -0,0 +1,346 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, Sudhakar Shet Kudtarkar (@kudtarkar1)
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l3out_extepg_to_contract
+short_description: Bind Contracts to External End Point Groups (EPGs)
+description:
+- Bind Contracts to External End Point Groups (EPGs) on ACI fabrics.
+options:
+ tenant:
+ description:
+ - Name of existing tenant.
+ type: str
+ l3out:
+ description:
+ - Name of the l3out.
+ type: str
+ aliases: ['l3out_name']
+ extepg:
+ description:
+ - Name of the external end point group.
+ type: str
+ aliases: ['extepg_name', 'external_epg']
+ contract:
+ description:
+ - Name of the contract.
+ type: str
+ contract_type:
+ description:
+ - The type of contract.
+ type: str
+ required: yes
+ choices: ['consumer', 'provider']
+ priority:
+ description:
+ - This has four levels of priority.
+ type: str
+ choices: ['level1', 'level2', 'level3', 'unspecified']
+ provider_match:
+ description:
+ - This is configurable for provided contracts.
+ type: str
+ choices: ['all', 'at_least_one', 'at_most_one', 'none']
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant), C(l3out) and C(extepg) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant), M(cisco.aci.aci_l3out) and M(cisco.aci.aci_l3out_extepg) modules can be used for this.
+seealso:
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fvtenant), B(l3extInstP) and B(l3extOut).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Sudhakar Shet Kudtarkar (@kudtarkar1)
+- Shreyas Srish (@shrsr)
+'''
+
+EXAMPLES = r'''
+- name: Bind a contract to an external EPG
+ cisco.aci.aci_l3out_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l3out: l3out
+ extepg : testEpg
+ contract: contract1
+ contract_type: provider
+ state: present
+ delegate_to: localhost
+
+- name: Remove existing contract from an external EPG
+ cisco.aco.aci_l3out_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: Auto-Demo
+ l3out: l3out
+ extepg : testEpg
+ contract: contract1
+ contract_type: provider
+ state: absent
+ delegate_to: localhost
+
+- name: Query a contract bound to an external EPG
+ cisco.aci.aci_l3out_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ tenant: ansible_tenant
+ l3out: ansible_l3out
+ extepg: ansible_extEpg
+ contract: ansible_contract
+ contract_type: provider
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all contracts relationships
+ cisco.aci.aci_l3out_epg_to_contract:
+ host: apic
+ username: admin
+ password: SomeSecretePassword
+ contract_type: provider
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+ current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+ error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+ raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>'
+ sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+ previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+ proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+ filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+ method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+ response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+ status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+ url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+ '''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+ACI_CLASS_MAPPING = dict(
+ consumer={
+ 'class': 'fvRsCons',
+ 'rn': 'rscons-',
+ },
+ provider={
+ 'class': 'fvRsProv',
+ 'rn': 'rsprov-',
+ },
+)
+
+PROVIDER_MATCH_MAPPING = dict(
+ all='All',
+ at_least_one='AtleastOne',
+ at_most_one='tmostOne',
+ none='None',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ contract_type=dict(type='str', required=True, choices=['consumer', 'provider']),
+ l3out=dict(type='str', aliases=['l3out_name']),
+ contract=dict(type='str'),
+ priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),
+ provider_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ tenant=dict(type='str'),
+ extepg=dict(type='str', aliases=['extepg_name', 'external_epg']),
+ )
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['extepg', 'contract', 'l3out', 'tenant']],
+ ['state', 'present', ['extepg', 'contract', 'l3out', 'tenant']],
+ ],
+ )
+
+ l3out = module.params.get('l3out')
+ contract = module.params.get('contract')
+ contract_type = module.params.get('contract_type')
+ extepg = module.params.get('extepg')
+ priority = module.params.get('priority')
+ provider_match = module.params.get('provider_match')
+ if provider_match is not None:
+ provider_match = PROVIDER_MATCH_MAPPING.get(provider_match)
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+
+ aci_class = ACI_CLASS_MAPPING.get(contract_type)["class"]
+ aci_rn = ACI_CLASS_MAPPING.get(contract_type)["rn"]
+
+ if contract_type == "consumer" and provider_match is not None:
+ module.fail_json(msg="the 'provider_match' is only configurable for Provided Contracts")
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l3extOut',
+ aci_rn='out-{0}'.format(l3out),
+ module_object=l3out,
+ target_filter={'name': l3out},
+ ),
+ subclass_2=dict(
+ aci_class='l3extInstP',
+ aci_rn='instP-{0}'.format(extepg),
+ module_object=extepg,
+ target_filter={'name': extepg},
+ ),
+ subclass_3=dict(
+ aci_class=aci_class,
+ aci_rn='{0}{1}'.format(aci_rn, contract),
+ module_object=contract,
+ target_filter={'tnVzBrCPName': contract},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=aci_class,
+ class_config=dict(
+ matchT=provider_match,
+ prio=priority,
+ tnVzBrCPName=contract,
+ ),
+ )
+
+ aci.get_diff(aci_class=aci_class)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py
new file mode 100644
index 00000000..cddd76a6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_extsubnet.py
@@ -0,0 +1,332 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l3out_extsubnet
+short_description: Manage External Subnet objects (l3extSubnet:extsubnet)
+description:
+- Manage External Subnet objects (l3extSubnet:extsubnet)
+options:
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ required: yes
+ l3out:
+ description:
+ - Name of an existing L3Out.
+ type: str
+ aliases: [ l3out_name ]
+ required: yes
+ extepg:
+ description:
+ - Name of an existing ExtEpg.
+ type: str
+ aliases: [ extepg_name ]
+ required: yes
+ network:
+ description:
+ - The network address for the Subnet.
+ type: str
+ aliases: [ address, ip ]
+ subnet_name:
+ description:
+ - Name of External Subnet being created.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - Description for the External Subnet.
+ type: str
+ aliases: [ descr ]
+ scope:
+ description:
+ - Determines the scope of the Subnet.
+ - The C(export-rtctrl) option controls which external networks are advertised out of the fabric using route-maps and IP prefix-lists.
+ - The C(import-security) option classifies for the external EPG.
+ The rules and contracts defined in this external EPG apply to networks matching this subnet.
+ - The C(shared-rtctrl) option controls which external prefixes are advertised to other tenants for shared services.
+ - The C(shared-security) option configures the classifier for the subnets in the VRF where the routes are leaked.
+ - The APIC defaults to C(import-security) when unset during creation.
+ default: [ import-security ]
+ type: list
+ elements: str
+ choices: [ export-rtctrl, import-security, shared-rtctrl, shared-security ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) and C(domain) and C(vrf) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_domain) and M(cisco.aci.aci_vrf) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_domain
+- module: cisco.aci.aci_vrf
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l3ext:Out).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Rostyslav Davydenko (@rost-d)
+- Cindy Zhao (@cizhao)
+'''
+
+EXAMPLES = r'''
+- name: Add a new External Subnet
+ cisco.aci.aci_l3out_extsubnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ l3out: prod_l3out
+ extepg: prod_extepg
+ description: External Subnet for Production ExtEpg
+ network: 192.0.2.0/24
+ scope: export-rtctrl
+ state: present
+ delegate_to: localhost
+
+- name: Delete External Subnet
+ cisco.aci.aci_l3out_extsubnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ l3out: prod_l3out
+ extepg: prod_extepg
+ network: 192.0.2.0/24
+ state: absent
+ delegate_to: localhost
+
+- name: Query ExtEpg Subnet information
+ cisco.aci.aci_l3out_extsubnet:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ l3out: prod_l3out
+ extepg: prod_extepg
+ network: 192.0.2.0/24
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', required=True, aliases=['tenant_name']),
+ l3out=dict(type='str', required=True, aliases=['l3out_name']),
+ extepg=dict(type='str', required=True, aliases=['extepg_name', 'name']),
+ network=dict(type='str', aliases=['address', 'ip']),
+ description=dict(type='str', aliases=['descr']),
+ subnet_name=dict(type='str', aliases=['name']),
+ scope=dict(type='list', elements='str', default=['import-security'], choices=['export-rtctrl', 'import-security', 'shared-rtctrl', 'shared-security']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'present', ['network']],
+ ['state', 'absent', ['network']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ tenant = module.params.get('tenant')
+ l3out = module.params.get('l3out')
+ extepg = module.params.get('extepg')
+ network = module.params.get('network')
+ description = module.params.get('description')
+ subnet_name = module.params.get('subnet_name')
+ scope = ','.join(sorted(module.params.get('scope')))
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l3extOut',
+ aci_rn='out-{0}'.format(l3out),
+ module_object=l3out,
+ target_filter={'name': l3out},
+ ),
+ subclass_2=dict(
+ aci_class='l3extInstP',
+ aci_rn='instP-{0}'.format(extepg),
+ module_object=extepg,
+ target_filter={'name': extepg},
+ ),
+ subclass_3=dict(
+ aci_class='l3extSubnet',
+ aci_rn='extsubnet-[{0}]'.format(network),
+ module_object=network,
+ target_filter={'name': network},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='l3extSubnet',
+ class_config=dict(
+ ip=network,
+ descr=description,
+ name=subnet_name,
+ scope=scope,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='l3extSubnet')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py
new file mode 100644
index 00000000..61110acb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_logical_interface_vpc_member.py
@@ -0,0 +1,340 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l3out_logical_interface_vpc_member
+short_description: Manage Member Node objects (l3extMember:Member)
+description:
+- Manage Member Node objects (l3extMember:Member)
+options:
+ description:
+ description:
+ - The description for the logical interface VPC member.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ l3out:
+ description:
+ - Name of an existing L3Out.
+ type: str
+ aliases: [ l3out_name ]
+ logical_node:
+ description:
+ - Name of an existing logical node profile.
+ type: str
+ logical_interface:
+ description:
+ - Name of an existing logical interface.
+ type: str
+ path_dn:
+ description:
+ - DN of existing path endpoints for VPC policy group used to reach external L3 network.
+ type: str
+ side:
+ description:
+ - Provides the side of member.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant), C(l3out), C(logical_node), C(logical_interface), C(path_dn) and C(member) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_l3out) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_l3out
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l3ext:Out).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Anvitha Jain(@anvitha-jain)
+'''
+
+EXAMPLES = r'''
+- name: Create a VPC member
+ cisco.aci.aci_l3out_logical_interface_vpc_member:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ l3out: l3out
+ logical_node: nodeName
+ logical_interface: interfaceName
+ path_dn: topology/pod-1/protpaths-101-102/pathep-[policy_group_name]
+ side: A
+ state: present
+ delegate_to: localhost
+
+- name: Delete a VPC member
+ cisco.aci.aci_l3out_logical_interface_vpc_member:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ l3out: l3out
+ logical_node: nodeName
+ logical_interface: interfaceName
+ path_dn: topology/pod-1/protpaths-101-102/pathep-[policy_group_name]
+ side: A
+ state: absent
+ delegate_to: localhost
+
+- name: Query all VPC members
+ cisco.aci.aci_l3out_logical_interface_vpc_member:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a specific VPC member under l3out
+ cisco.aci.aci_l3out_logical_interface_vpc_member:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ l3out: l3out
+ logical_node: nodeName
+ logical_interface: interfaceName
+ path_dn: topology/pod-1/protpaths-101-102/pathep-[policy_group_name]
+ side: A
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ l3out=dict(type='str', aliases=['l3out_name']), # Not required for querying all objects
+ logical_node=dict(type='str'), # Not required for querying all objects
+ logical_interface=dict(type='str'),
+ path_dn=dict(type='str'),
+ side=dict(type='str'),
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'present', ['side', 'path_dn', 'logical_interface', 'logical_node', 'l3out', 'tenant']],
+ ['state', 'absent', ['side', 'path_dn', 'logical_interface', 'logical_node', 'l3out', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ tenant = module.params.get('tenant')
+ l3out = module.params.get('l3out')
+ logical_node = module.params.get('logical_node')
+ logical_interface = module.params.get('logical_interface')
+ path_dn = module.params.get('path_dn')
+ side = module.params.get('side')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l3extOut',
+ aci_rn='out-{0}'.format(l3out),
+ module_object=l3out,
+ target_filter={'name': l3out},
+ ),
+ subclass_2=dict(
+ aci_class='l3extLNodeP',
+ aci_rn='lnodep-{0}'.format(logical_node),
+ module_object=logical_node,
+ target_filter={'name': logical_node},
+ ),
+ subclass_3=dict(
+ aci_class='l3extLIfP',
+ aci_rn='/lifp-{0}'.format(logical_interface),
+ module_object=logical_interface,
+ target_filter={'name': logical_interface},
+ ),
+ subclass_4=dict(
+ aci_class='l3extRsPathL3OutAtt',
+ aci_rn='/rspathL3OutAtt-[{0}]'.format(path_dn),
+ module_object=path_dn,
+ target_filter={'name': path_dn},
+ ),
+ subclass_5=dict(
+ aci_class='l3extMember',
+ aci_rn='/mem-{0}'.format(side),
+ module_object=side,
+ target_filter={'name': side},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='l3extMember',
+ class_config=dict(
+ name=side,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='l3extMember')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_route_tag_policy.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_route_tag_policy.py
new file mode 100644
index 00000000..412a492d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_route_tag_policy.py
@@ -0,0 +1,255 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l3out_route_tag_policy
+short_description: Manage route tag policies (l3ext:RouteTagPol)
+description:
+- Manage route tag policies on Cisco ACI fabrics.
+options:
+ rtp:
+ description:
+ - The name of the route tag policy.
+ type: str
+ aliases: [ name, rtp_name ]
+ description:
+ description:
+ - The description for the route tag policy.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ tag:
+ description:
+ - The value of the route tag.
+ - Accepted values range between C(0) and C(4294967295).
+ - The APIC defaults to C(4294967295) when unset during creation.
+ type: int
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l3ext:RouteTagPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- cisco.aci.aci_l3out_route_tag_policy:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ rtp: '{{ rtp_name }}'
+ tenant: production
+ tag: '{{ tag }}'
+ description: '{{ description }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ rtp=dict(type='str', aliases=['name', 'rtp_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ tag=dict(type='int'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['rtp', 'tenant']],
+ ['state', 'present', ['rtp', 'tenant']],
+ ],
+ )
+
+ rtp = module.params.get('rtp')
+ description = module.params.get('description')
+ tag = module.params.get('tag')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l3extRouteTagPol',
+ aci_rn='rttag-{0}'.format(rtp),
+ module_object=rtp,
+ target_filter={'name': rtp},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='l3extRouteTagPol',
+ class_config=dict(
+ name=rtp,
+ descr=description, tag=tag,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='l3extRouteTagPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py
new file mode 100644
index 00000000..2faf6e3b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_l3out_static_routes.py
@@ -0,0 +1,368 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2020, 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_l3out_static_routes
+short_description: Manage Static routes object (l3ext:ipRouteP)
+description:
+- Manage External Subnet objects (l3ext:ipRouteP)
+options:
+ description:
+ description:
+ - The description for the static routes.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ l3out:
+ description:
+ - Name of an existing L3Out.
+ type: str
+ aliases: [ l3out_name ]
+ logical_node:
+ description:
+ - Name of an existing logical node profile.
+ type: str
+ pod_id:
+ description:
+ - Existing podId.
+ type: int
+ node_id:
+ description:
+ - Existing nodeId.
+ type: int
+ prefix:
+ description:
+ - Configure IP and next hop IP for the routed outside network.
+ type: str
+ aliases: [ route ]
+ track_policy:
+ description:
+ - Relation definition for static route to TrackList.
+ type: str
+ preference:
+ description:
+ - Administrative preference value for the route.
+ type: int
+ bfd:
+ description:
+ - Determines if bfd is required for route control.
+ - The APIC defaults to C(null) when unset during creation.
+ type: str
+ choices: [ bfd, null ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant), C(l3out), C(logical_node), C(fabric_node) and C(prefix) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_l3out) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_l3out
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(l3ext:Out).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Anvitha Jain(@anvitha-jain)
+'''
+
+EXAMPLES = r'''
+- name: Create static routes
+ cisco.aci.aci_l3out_static_routes:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ l3out: l3out
+ logical_node: nodeName
+ node_id: 101
+ pod_id: 1
+ prefix: 10.10.0.0/16
+ delegate_to: localhost
+
+- name: Delete static routes
+ cisco.aci.aci_l3out_static_routes:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ l3out: l3out
+ logical_node: nodeName
+ node_id: 101
+ pod_id: 1
+ prefix: 10.10.0.0/16
+ delegate_to: localhost
+
+- name: Query for a specific MO under l3out
+ cisco.aci.aci_l3out_static_routes:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: tenantName
+ l3out: l3out
+ logical_node: nodeName
+ node_id: 101
+ pod_id: 1
+ prefix: 10.10.0.0/16
+ delegate_to: localhost
+
+- name: Query for all static routes
+ cisco.aci.aci_l3out_static_routes:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ l3out=dict(type='str', aliases=['l3out_name']), # Not required for querying all objects
+ logical_node=dict(type='str'), # Not required for querying all objects
+ pod_id=dict(type='int'),
+ node_id=dict(type='int'),
+ prefix=dict(type='str', aliases=['route']),
+ track_policy=dict(type='str'),
+ preference=dict(type='int'),
+ bfd=dict(type='str', choices=['bfd', None]),
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'present', ['prefix', 'node_id', 'pod_id', 'logical_node', 'l3out', 'tenant']],
+ ['state', 'absent', ['prefix', 'node_id', 'pod_id', 'logical_node', 'l3out', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ tenant = module.params.get('tenant')
+ l3out = module.params.get('l3out')
+ logical_node = module.params.get('logical_node')
+ node_id = module.params.get('node_id')
+ pod_id = module.params.get('pod_id')
+ prefix = module.params.get('prefix')
+ track_policy = module.params.get('track_policy')
+ preference = module.params.get('preference')
+ bfd = module.params.get('bfd')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ fabric_node = 'topology/pod-{0}/node-{1}'.format(pod_id, node_id)
+ child_classes = ['ipNexthopP']
+ if track_policy is not None:
+ child_classes.append('ipRsRouteTrack')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='l3extOut',
+ aci_rn='out-{0}'.format(l3out),
+ module_object=l3out,
+ target_filter={'name': l3out},
+ ),
+ subclass_2=dict(
+ aci_class='l3extLNodeP',
+ aci_rn='lnodep-{0}'.format(logical_node),
+ module_object=logical_node,
+ target_filter={'name': logical_node},
+ ),
+ subclass_3=dict(
+ aci_class='l3extRsNodeL3OutAtt',
+ aci_rn='/rsnodeL3OutAtt-[{0}]'.format(fabric_node),
+ module_object=fabric_node,
+ target_filter={'name': fabric_node},
+ ),
+ subclass_4=dict(
+ aci_class='ipRouteP',
+ aci_rn='/rt-[{0}]'.format(prefix),
+ module_object=prefix,
+ target_filter={'name': prefix},
+ ),
+ child_classes=child_classes
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ child_configs = []
+ class_config = dict(
+ descr=description,
+ ip=prefix,
+ pref=preference,
+ nameAlias=name_alias,
+ )
+ if bfd is not None:
+ class_config['rtCtrl'] = bfd
+
+ if track_policy is not None:
+ tDn = 'uni/tn-{0}/tracklist-{1}'.format(tenant, track_policy)
+ child_configs.append({'ipRsRouteTrack': {'attributes': {'tDn': tDn}}})
+
+ aci.payload(
+ aci_class='ipRouteP',
+ class_config=class_config,
+ child_configs=child_configs
+ ),
+
+ aci.get_diff(aci_class='ipRouteP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group.py
new file mode 100644
index 00000000..2df19b7d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group.py
@@ -0,0 +1,236 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+module: aci_maintenance_group
+short_description: This creates an ACI maintenance group
+notes:
+ - a maintenance policy (aci_maintenance_policy must be created prior to creating an aci maintenance group
+description:
+ - This modules creates an ACI maintenance group
+options:
+ group:
+ description:
+ - This is the name of the group
+ type: str
+ policy:
+ description:
+ - This is the name of the policy that was created using aci_maintenance_policy
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [absent, present, query]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+author:
+ - Steven Gerhart (@sgerhart)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: maintenance group
+ cisco.aci.aci_maintenance_group:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ group: maintenancegrp1
+ policy: maintenancePol1
+ state: present
+'''
+
+RETURN = '''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ group=dict(type='str'), # Not required for querying all objects
+ policy=dict(type='str'), # Not required for querying all objects
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['group']],
+ ['state', 'present', ['group']],
+ ],
+ )
+
+ state = module.params.get('state')
+ group = module.params.get('group')
+ policy = module.params.get('policy')
+ name_alias = module.params.get('name_alias')
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='maintMaintGrp',
+ aci_rn='fabric/maintgrp-{0}'.format(group),
+ target_filter={'name': group},
+ module_object=group,
+ ),
+ child_classes=['maintRsMgrpp'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='maintMaintGrp',
+ class_config=dict(
+ name=group,
+ nameAlias=name_alias,
+ ),
+ child_configs=[
+ dict(
+ maintRsMgrpp=dict(
+ attributes=dict(
+ tnMaintMaintPName=policy,
+ ),
+ ),
+ ),
+ ],
+
+ )
+
+ aci.get_diff(aci_class='maintMaintGrp')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py
new file mode 100644
index 00000000..3043c466
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_group_node.py
@@ -0,0 +1,242 @@
+#!/usr/bin/python
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = r'''
+---
+module: aci_maintenance_group_node
+short_description: Manage maintenance group nodes
+description:
+- Manage maintenance group nodes
+options:
+ group:
+ description:
+ - The maintenance group name that you want to add the node to.
+ type: str
+ node:
+ description:
+ - The node to be added to the maintenance group.
+ - The value equals the nodeid.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+author:
+- Steven Gerhart (@sgerhart)
+'''
+
+EXAMPLES = r'''
+- name: maintenance group
+ cisco.aci.aci_maintenance_group_node:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ group: maintenancegrp1
+ node: 1001
+ state: present
+
+- name: maintenance group
+ cisco.aci.aci_maintenance_group_node:
+ host: "{{ inventory_hostname }}"
+ username: "{{ user }}"
+ password: "{{ pass }}"
+ validate_certs: no
+ group: maintenancegrp1
+ node: 1002
+ state: absent
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ group=dict(type='str'), # Not required for querying all objects
+ node=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['node', 'group']],
+ ['state', 'present', ['node', 'group']],
+ ],
+ )
+
+ state = module.params.get('state')
+ group = module.params.get('group')
+ node = module.params.get('node')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='maintMaintGrp',
+ aci_rn='fabric/maintgrp-{0}'.format(group),
+ target_filter={'name': group},
+ module_object=group,
+ ),
+ subclass_1=dict(
+ aci_class='fabricNodeBlk',
+ aci_rn='nodeblk-blk{0}-{0}'.format(node),
+ target_filter={'name': 'blk{0}-{0}'.format(node)},
+ module_object=node,
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fabricNodeBlk',
+ class_config=dict(
+ from_=node,
+ to_=node,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='fabricNodeBlk')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_policy.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_policy.py
new file mode 100644
index 00000000..b067e1d5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_maintenance_policy.py
@@ -0,0 +1,277 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = r'''
+---
+module: aci_maintenance_policy
+short_description: Manage firmware maintenance policies
+description:
+- Manage maintenance policies that defines behavior during an ACI upgrade.
+options:
+ name:
+ description:
+ - The name for the maintenance policy.
+ type: str
+ aliases: [ maintenance_policy ]
+ runmode:
+ description:
+ - Whether the system pauses on error or just continues through it.
+ type: str
+ choices: [ pauseOnlyOnFailures, pauseNever ]
+ default: pauseOnlyOnFailures
+ graceful:
+ description:
+ - Whether the system will bring down the nodes gracefully during an upgrade, which reduces traffic lost.
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ scheduler:
+ description:
+ - The name of scheduler that is applied to the policy.
+ type: str
+ adminst:
+ description:
+ - Will trigger an immediate upgrade for nodes if adminst is set to triggered.
+ type: str
+ choices: [ triggered, untriggered ]
+ default: untriggered
+ ignoreCompat:
+ description:
+ - To check whether compatibility checks should be ignored
+ - The APIC defaults to C(no) when unset during creation.
+ type: bool
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- A scheduler is required for this module, which could have been created using the M(cisco.aci.aci_fabric_scheduler) module or via the UI.
+author:
+- Steven Gerhart (@sgerhart)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- name: Ensure maintenance policy is present
+ cisco.aci.aci_maintenance_policy:
+ host: '{{ inventory_hostname }}'
+ username: '{{ user }}'
+ password: '{{ pass }}'
+ validate_certs: no
+ name: maintenancePol1
+ scheduler: simpleScheduler
+ runmode: False
+ state: present
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ name=dict(type='str', aliases=['maintenance_policy']), # Not required for querying all objects
+ runmode=dict(type='str', default='pauseOnlyOnFailures', choices=['pauseOnlyOnFailures', 'pauseNever']),
+ graceful=dict(type='bool'),
+ scheduler=dict(type='str'),
+ ignoreCompat=dict(type='bool'),
+ adminst=dict(type='str', default='untriggered', choices=['triggered', 'untriggered']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['name']],
+ ['state', 'present', ['name', 'scheduler']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ state = module.params.get('state')
+ name = module.params.get('name')
+ runmode = module.params.get('runmode')
+ scheduler = module.params.get('scheduler')
+ adminst = module.params.get('adminst')
+ graceful = aci.boolean(module.params.get('graceful'))
+ ignoreCompat = aci.boolean(module.params.get('ignoreCompat'))
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='maintMaintP',
+ aci_rn='fabric/maintpol-{0}'.format(name),
+ target_filter={'name': name},
+ module_object=name,
+ ),
+ child_classes=['maintRsPolScheduler']
+
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='maintMaintP',
+ class_config=dict(
+ name=name,
+ runMode=runmode,
+ graceful=graceful,
+ adminSt=adminst,
+ ignoreCompat=ignoreCompat,
+ nameAlias=name_alias,
+ ),
+ child_configs=[
+ dict(
+ maintRsPolScheduler=dict(
+ attributes=dict(
+ tnTrigSchedPName=scheduler,
+ ),
+ ),
+ ),
+ ],
+
+ )
+
+ aci.get_diff(aci_class='maintMaintP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_rest.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_rest.py
new file mode 100644
index 00000000..2e18c548
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_rest.py
@@ -0,0 +1,451 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_rest
+short_description: Direct access to the Cisco APIC REST API
+description:
+- Enables the management of the Cisco ACI fabric through direct access to the Cisco APIC REST API.
+- Thanks to the idempotent nature of the APIC, this module is idempotent and reports changes.
+requirements:
+- lxml (when using XML payload)
+- xmljson >= 0.1.8 (when using XML payload)
+- python 2.7+ (when using xmljson)
+options:
+ method:
+ description:
+ - The HTTP method of the request.
+ - Using C(delete) is typically used for deleting objects.
+ - Using C(get) is typically used for querying objects.
+ - Using C(post) is typically used for modifying objects.
+ type: str
+ choices: [ delete, get, post ]
+ default: get
+ aliases: [ action ]
+ path:
+ description:
+ - URI being used to execute API calls.
+ - Must end in C(.xml) or C(.json).
+ type: str
+ required: yes
+ aliases: [ uri ]
+ content:
+ description:
+ - When used instead of C(src), sets the payload of the API request directly.
+ - This may be convenient to template simple requests.
+ - For anything complex use the C(template) lookup plugin (see examples)
+ or the M(template) module with parameter C(src).
+ type: raw
+ src:
+ description:
+ - Name of the absolute path of the filename that includes the body
+ of the HTTP request being sent to the ACI fabric.
+ - If you require a templated payload, use the C(content) parameter
+ together with the C(template) lookup plugin, or use M(template).
+ type: path
+ aliases: [ config_file ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- Certain payloads are known not to be idempotent, so be careful when constructing payloads,
+ e.g. using C(status="created") will cause idempotency issues, use C(status="modified") instead.
+ More information in :ref:`the ACI documentation <aci_guide_known_issues>`.
+- Certain payloads (and used paths) are known to report no changes happened when changes did happen.
+ This is a known APIC problem and has been reported to the vendor. A workaround for this issue exists.
+ More information in :ref:`the ACI documentation <aci_guide_known_issues>`.
+- XML payloads require the C(lxml) and C(xmljson) python libraries. For JSON payloads nothing special is needed.
+- If you do not have any attributes, it may be necessary to add the "attributes" key with an empty dictionnary "{}" for value
+ as the APIC does expect the entry to precede any children.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: Cisco APIC REST API Configuration Guide
+ description: More information about the APIC REST API.
+ link: http://www.cisco.com/c/en/us/td/docs/switches/datacenter/aci/apic/sw/2-x/rest_cfg/2_1_x/b_Cisco_APIC_REST_API_Configuration_Guide.html
+author:
+- Dag Wieers (@dagwieers)
+- Cindy Zhao (@cizhao)
+'''
+
+EXAMPLES = r'''
+- name: Add a tenant using certificate authentication
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/admin.key
+ method: post
+ path: /api/mo/uni.xml
+ src: /home/cisco/ansible/aci/configs/aci_config.xml
+ delegate_to: localhost
+
+- name: Add a tenant from a templated payload file from templates/
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/admin.key
+ method: post
+ path: /api/mo/uni.xml
+ content: "{{ lookup('template', 'aci/tenant.xml.j2') }}"
+ delegate_to: localhost
+
+- name: Add a tenant using inline YAML
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/admin.key
+ validate_certs: no
+ path: /api/mo/uni.json
+ method: post
+ content:
+ fvTenant:
+ attributes:
+ name: Sales
+ descr: Sales department
+ delegate_to: localhost
+
+- name: Add a tenant using a JSON string
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/admin.key
+ validate_certs: no
+ path: /api/mo/uni.json
+ method: post
+ content:
+ {
+ "fvTenant": {
+ "attributes": {
+ "name": "Sales",
+ "descr": "Sales department"
+ }
+ }
+ }
+ delegate_to: localhost
+
+- name: Add a tenant using an XML string
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/{{ aci_username }}.key
+ validate_certs: no
+ path: /api/mo/uni.xml
+ method: post
+ content: '<fvTenant name="Sales" descr="Sales departement"/>'
+ delegate_to: localhost
+
+- name: Get tenants using password authentication
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ method: get
+ path: /api/node/class/fvTenant.json
+ delegate_to: localhost
+ register: query_result
+
+- name: Configure contracts
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/admin.key
+ method: post
+ path: /api/mo/uni.xml
+ src: /home/cisco/ansible/aci/configs/contract_config.xml
+ delegate_to: localhost
+
+- name: Register leaves and spines
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/admin.key
+ validate_certs: no
+ method: post
+ path: /api/mo/uni/controller/nodeidentpol.xml
+ content:
+ <fabricNodeIdentPol>
+ <fabricNodeIdentP name="{{ item.name }}" nodeId="{{ item.nodeid }}" status="{{ item.status }}" serial="{{ item.serial }}"/>
+ </fabricNodeIdentPol>
+ with_items:
+ - '{{ apic_leavesspines }}'
+ delegate_to: localhost
+
+- name: Wait for all controllers to become ready
+ cisco.aci.aci_rest:
+ host: apic
+ username: admin
+ private_key: pki/admin.key
+ validate_certs: no
+ path: /api/node/class/topSystem.json?query-target-filter=eq(topSystem.role,"controller")
+ register: apics
+ until: "'totalCount' in apics and apics.totalCount|int >= groups['apic']|count"
+ retries: 120
+ delay: 30
+ delegate_to: localhost
+ run_once: yes
+'''
+
+RETURN = r'''
+error_code:
+ description: The REST ACI return code, useful for troubleshooting on failure
+ returned: always
+ type: int
+ sample: 122
+error_text:
+ description: The REST ACI descriptive text, useful for troubleshooting on failure
+ returned: always
+ type: str
+ sample: unknown managed object class foo
+imdata:
+ description: Converted output returned by the APIC REST (register this for post-processing)
+ returned: always
+ type: str
+ sample: [{"error": {"attributes": {"code": "122", "text": "unknown managed object class foo"}}}]
+payload:
+ description: The (templated) payload send to the APIC REST API (xml or json)
+ returned: always
+ type: str
+ sample: '<foo bar="boo"/>'
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+response:
+ description: HTTP response string
+ returned: always
+ type: str
+ sample: 'HTTP Error 400: Bad Request'
+status:
+ description: HTTP status code
+ returned: always
+ type: int
+ sample: 400
+totalCount:
+ description: Number of items in the imdata array
+ returned: always
+ type: str
+ sample: '0'
+url:
+ description: URL used for APIC REST call
+ returned: success
+ type: str
+ sample: https://1.2.3.4/api/mo/uni/tn-[Dag].json?rsp-subtree=modified
+'''
+
+import json
+import os
+
+try:
+ from ansible.module_utils.six.moves.urllib.parse import parse_qsl, urlencode, urlparse, urlunparse
+ HAS_URLPARSE = True
+except Exception:
+ HAS_URLPARSE = False
+
+# Optional, only used for XML payload
+try:
+ from lxml import etree # noqa
+ HAS_LXML_ETREE = True
+except ImportError:
+ HAS_LXML_ETREE = False
+
+# Optional, only used for XML payload
+try:
+ from xmljson import cobra # noqa
+ HAS_XMLJSON_COBRA = True
+except ImportError:
+ HAS_XMLJSON_COBRA = False
+
+# Optional, only used for YAML validation
+try:
+ import yaml
+ HAS_YAML = True
+except Exception:
+ HAS_YAML = False
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.urls import fetch_url
+from ansible.module_utils._text import to_text
+
+
+def update_qsl(url, params):
+ ''' Add or update a URL query string '''
+
+ if HAS_URLPARSE:
+ url_parts = list(urlparse(url))
+ query = dict(parse_qsl(url_parts[4]))
+ query.update(params)
+ url_parts[4] = urlencode(query)
+ return urlunparse(url_parts)
+ elif '?' in url:
+ return url + '&' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()])
+ else:
+ return url + '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()])
+
+
+class ACIRESTModule(ACIModule):
+
+ def changed(self, d):
+ ''' Check ACI response for changes '''
+
+ if isinstance(d, dict):
+ for k, v in d.items():
+ if k == 'status' and v in ('created', 'modified', 'deleted'):
+ return True
+ elif self.changed(v) is True:
+ return True
+ elif isinstance(d, list):
+ for i in d:
+ if self.changed(i) is True:
+ return True
+
+ return False
+
+ def response_type(self, rawoutput, rest_type='xml'):
+ ''' Handle APIC response output '''
+
+ if rest_type == 'json':
+ self.response_json(rawoutput)
+ else:
+ self.response_xml(rawoutput)
+
+ # Use APICs built-in idempotency
+ if HAS_URLPARSE:
+ self.result['changed'] = self.changed(self.imdata)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ path=dict(type='str', required=True, aliases=['uri']),
+ method=dict(type='str', default='get', choices=['delete', 'get', 'post'], aliases=['action']),
+ src=dict(type='path', aliases=['config_file']),
+ content=dict(type='raw'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=[['content', 'src']],
+ )
+
+ content = module.params.get('content')
+ path = module.params.get('path')
+ src = module.params.get('src')
+
+ # Report missing file
+ file_exists = False
+ if src:
+ if os.path.isfile(src):
+ file_exists = True
+ else:
+ module.fail_json(msg="Cannot find/access src '%s'" % src)
+
+ # Find request type
+ if path.find('.xml') != -1:
+ rest_type = 'xml'
+ if not HAS_LXML_ETREE:
+ module.fail_json(msg='The lxml python library is missing, or lacks etree support.')
+ if not HAS_XMLJSON_COBRA:
+ module.fail_json(msg='The xmljson python library is missing, or lacks cobra support.')
+ elif path.find('.json') != -1:
+ rest_type = 'json'
+ else:
+ module.fail_json(msg='Failed to find REST API payload type (neither .xml nor .json).')
+
+ aci = ACIRESTModule(module)
+ aci.result['status'] = -1 # Ensure we always return a status
+
+ # We include the payload as it may be templated
+ payload = content
+ if file_exists:
+ with open(src, 'r') as config_object:
+ # TODO: Would be nice to template this, requires action-plugin
+ payload = config_object.read()
+ payload_output_file = json.loads(payload)
+
+ # Validate payload
+ if rest_type == 'json':
+ if content and isinstance(content, dict):
+ # Validate inline YAML/JSON
+ payload = json.dumps(payload)
+ elif payload and isinstance(payload, str) and HAS_YAML:
+ try:
+ # Validate YAML/JSON string
+ payload = json.dumps(yaml.safe_load(payload))
+ except Exception as e:
+ module.fail_json(msg='Failed to parse provided JSON/YAML payload: %s' % to_text(e), exception=to_text(e), payload=payload)
+ elif rest_type == 'xml' and HAS_LXML_ETREE:
+ if content and isinstance(content, dict) and HAS_XMLJSON_COBRA:
+ # Validate inline YAML/JSON
+ payload = etree.tostring(cobra.etree(payload)[0])
+ elif payload and isinstance(payload, str):
+ try:
+ # Validate XML string
+ payload = etree.tostring(etree.fromstring(payload))
+ except Exception as e:
+ module.fail_json(msg='Failed to parse provided XML payload: %s' % to_text(e), payload=payload)
+
+ # Perform actual request using auth cookie (Same as aci.request(), but also supports XML)
+ if 'port' in aci.params and aci.params.get('port') is not None:
+ aci.url = '%(protocol)s://%(host)s:%(port)s/' % aci.params + path.lstrip('/')
+ else:
+ aci.url = '%(protocol)s://%(host)s/' % aci.params + path.lstrip('/')
+ if aci.params.get('method') != 'get':
+ path += '?rsp-subtree=modified'
+ aci.url = update_qsl(aci.url, {'rsp-subtree': 'modified'})
+
+ # Sign and encode request as to APIC's wishes
+ if aci.params.get('private_key') is not None:
+ aci.cert_auth(path=path, payload=payload)
+
+ aci.method = aci.params.get('method').upper()
+
+ # Perform request
+ resp, info = fetch_url(module, aci.url,
+ data=payload,
+ headers=aci.headers,
+ method=aci.method,
+ timeout=aci.params.get('timeout'),
+ use_proxy=aci.params.get('use_proxy'))
+
+ aci.response = info.get('msg')
+ aci.status = info.get('status')
+
+ # Report failure
+ if info.get('status') != 200:
+ try:
+ # APIC error
+ aci.response_type(info.get('body'), rest_type)
+ aci.fail_json(msg='APIC Error %(code)s: %(text)s' % aci.error)
+ except KeyError:
+ # Connection error
+ aci.fail_json(msg='Connection failed for %(url)s. %(msg)s' % info)
+
+ aci.response_type(resp.read(), rest_type)
+
+ aci.result['imdata'] = aci.imdata
+ aci.result['totalCount'] = aci.totalCount
+
+ output_path = aci.params.get('output_path')
+ if(output_path is not None):
+ with open(output_path, "a") as output_file:
+ json.dump([payload_output_file], output_file)
+
+ # Report success
+ aci.exit_json(**aci.result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_static_binding_to_epg.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_static_binding_to_epg.py
new file mode 100644
index 00000000..15677831
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_static_binding_to_epg.py
@@ -0,0 +1,441 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_static_binding_to_epg
+short_description: Bind static paths to EPGs (fv:RsPathAtt)
+description:
+- Bind static paths to EPGs on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - Name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ ap:
+ description:
+ - Name of an existing application network profile, that will contain the EPGs.
+ type: str
+ aliases: [ app_profile, app_profile_name ]
+ epg:
+ description:
+ - The name of the end point group.
+ type: str
+ aliases: [ epg_name ]
+ description:
+ description:
+ - Description for the static path to EPG binding.
+ type: str
+ aliases: [ descr ]
+ encap_id:
+ description:
+ - The encapsulation ID associating the C(epg) with the interface path.
+ - This acts as the secondary C(encap_id) when using micro-segmentation.
+ - Accepted values are any valid encap ID for specified encap, currently ranges between C(1) and C(4096).
+ type: int
+ aliases: [ vlan, vlan_id ]
+ primary_encap_id:
+ description:
+ - Determines the primary encapsulation ID associating the C(epg)
+ with the interface path when using micro-segmentation.
+ - Accepted values are any valid encap ID for specified encap, currently ranges between C(1) and C(4096).
+ type: int
+ aliases: [ primary_vlan, primary_vlan_id ]
+ deploy_immediacy:
+ description:
+ - The Deployment Immediacy of Static EPG on PC, VPC or Interface.
+ - The APIC defaults to C(lazy) when unset during creation.
+ type: str
+ choices: [ immediate, lazy ]
+ interface_mode:
+ description:
+ - Determines how layer 2 tags will be read from and added to frames.
+ - Values C(802.1p) and C(native) are identical.
+ - Values C(access) and C(untagged) are identical.
+ - Values C(regular), C(tagged) and C(trunk) are identical.
+ - The APIC defaults to C(trunk) when unset during creation.
+ type: str
+ choices: [ 802.1p, access, native, regular, tagged, trunk, untagged ]
+ aliases: [ interface_mode_name, mode ]
+ interface_type:
+ description:
+ - The type of interface for the static EPG deployment.
+ type: str
+ choices: [ fex, port_channel, switch_port, vpc ]
+ default: switch_port
+ pod_id:
+ description:
+ - The pod number part of the tDn.
+ - C(pod_id) is usually an integer below C(10).
+ type: int
+ aliases: [ pod, pod_number ]
+ leafs:
+ description:
+ - The switch ID(s) that the C(interface) belongs to.
+ - When C(interface_type) is C(switch_port), C(port_channel), or C(fex), then C(leafs) is a string of the leaf ID.
+ - When C(interface_type) is C(vpc), then C(leafs) is a list with both leaf IDs.
+ - The C(leafs) value is usually something like '101' or '101-102' depending on C(connection_type).
+ type: list
+ elements: str
+ aliases: [ leaves, nodes, paths, switches ]
+ interface:
+ description:
+ - The C(interface) string value part of the tDn.
+ - Usually a policy group like C(test-IntPolGrp) or an interface of the following format C(1/7) depending on C(interface_type).
+ type: str
+ extpaths:
+ description:
+ - The C(extpaths) integer value part of the tDn.
+ - C(extpaths) is only used if C(interface_type) is C(fex).
+ - Usually something like C(1011).
+ type: int
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant), C(ap), C(epg) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant), M(cisco.aci.aci_ap), M(cisco.aci.aci_epg) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_ap
+- module: cisco.aci.aci_epg
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:RsPathAtt).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+'''
+
+EXAMPLES = r'''
+- name: Deploy Static Path binding for given EPG
+ cisco.aci.aci_static_binding_to_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: accessport-code-cert
+ ap: accessport_code_app
+ epg: accessport_epg1
+ encap_id: 222
+ deploy_immediacy: lazy
+ interface_mode: untagged
+ interface_type: switch_port
+ pod_id: 1
+ leafs: 101
+ interface: '1/7'
+ state: present
+ delegate_to: localhost
+
+- name: Remove Static Path binding for given EPG
+ cisco.aci.aci_static_binding_to_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: accessport-code-cert
+ ap: accessport_code_app
+ epg: accessport_epg1
+ interface_type: switch_port
+ pod: 1
+ leafs: 101
+ interface: '1/7'
+ state: absent
+ delegate_to: localhost
+
+- name: Get specific Static Path binding for given EPG
+ cisco.aci.aci_static_binding_to_epg:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: accessport-code-cert
+ ap: accessport_code_app
+ epg: accessport_epg1
+ interface_type: switch_port
+ pod: 1
+ leafs: 101
+ interface: '1/7'
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+INTERFACE_MODE_MAPPING = {
+ '802.1p': 'native',
+ 'access': 'untagged',
+ 'native': 'native',
+ 'regular': 'regular',
+ 'tagged': 'regular',
+ 'trunk': 'regular',
+ 'untagged': 'untagged',
+}
+
+INTERFACE_TYPE_MAPPING = dict(
+ fex='topology/pod-{pod_id}/paths-{leafs}/extpaths-{extpaths}/pathep-[eth{interface}]',
+ port_channel='topology/pod-{pod_id}/paths-{leafs}/pathep-[{interface}]',
+ switch_port='topology/pod-{pod_id}/paths-{leafs}/pathep-[eth{interface}]',
+ vpc='topology/pod-{pod_id}/protpaths-{leafs}/pathep-[{interface}]',
+)
+
+# TODO: change 'deploy_immediacy' to 'resolution_immediacy' (as seen in aci_epg_to_domain)?
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects
+ epg=dict(type='str', aliases=['epg_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ encap_id=dict(type='int', aliases=['vlan', 'vlan_id']),
+ primary_encap_id=dict(type='int', aliases=['primary_vlan', 'primary_vlan_id']),
+ deploy_immediacy=dict(type='str', choices=['immediate', 'lazy']),
+ interface_mode=dict(type='str', choices=['802.1p', 'access', 'native', 'regular', 'tagged', 'trunk', 'untagged'],
+ aliases=['interface_mode_name', 'mode']),
+ interface_type=dict(type='str', default='switch_port', choices=['fex', 'port_channel', 'switch_port', 'vpc']),
+ pod_id=dict(type='int', aliases=['pod', 'pod_number']), # Not required for querying all objects
+ leafs=dict(type='list', elements='str', aliases=['leaves', 'nodes', 'paths', 'switches']), # Not required for querying all objects
+ interface=dict(type='str'), # Not required for querying all objects
+ extpaths=dict(type='int'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['interface_type', 'fex', ['extpaths']],
+ ['state', 'absent', ['ap', 'epg', 'interface', 'leafs', 'pod_id', 'tenant']],
+ ['state', 'present', ['ap', 'encap_id', 'epg', 'interface', 'leafs', 'pod_id', 'tenant']],
+ ],
+ )
+
+ tenant = module.params.get('tenant')
+ ap = module.params.get('ap')
+ epg = module.params.get('epg')
+ description = module.params.get('description')
+ encap_id = module.params.get('encap_id')
+ primary_encap_id = module.params.get('primary_encap_id')
+ deploy_immediacy = module.params.get('deploy_immediacy')
+ interface_mode = module.params.get('interface_mode')
+ interface_type = module.params.get('interface_type')
+ pod_id = module.params.get('pod_id')
+ leafs = module.params.get('leafs')
+ if leafs is not None:
+ # Process leafs, and support dash-delimited leafs
+ leafs = []
+ for leaf in module.params.get('leafs'):
+ # Users are likely to use integers for leaf IDs, which would raise an exception when using the join method
+ leafs.extend(str(leaf).split('-'))
+ if len(leafs) == 1:
+ if interface_type == 'vpc':
+ module.fail_json(msg='A interface_type of "vpc" requires 2 leafs')
+ leafs = leafs[0]
+ elif len(leafs) == 2:
+ if interface_type != 'vpc':
+ module.fail_json(msg='The interface_types "switch_port", "port_channel", and "fex" \
+ do not support using multiple leafs for a single binding')
+ leafs = "-".join(leafs)
+ else:
+ module.fail_json(msg='The "leafs" parameter must not have more than 2 entries')
+ interface = module.params.get('interface')
+ extpaths = module.params.get('extpaths')
+ state = module.params.get('state')
+
+ if encap_id is not None:
+ if encap_id not in range(1, 4097):
+ module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
+ encap_id = 'vlan-{0}'.format(encap_id)
+
+ if primary_encap_id is not None:
+ if primary_encap_id not in range(1, 4097):
+ module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
+ primary_encap_id = 'vlan-{0}'.format(primary_encap_id)
+
+ static_path = INTERFACE_TYPE_MAPPING[interface_type].format(pod_id=pod_id, leafs=leafs, extpaths=extpaths, interface=interface)
+
+ path_target_filter = {}
+ if pod_id is not None and leafs is not None and interface is not None and (interface_type != 'fex' or extpaths is not None):
+ path_target_filter = {'tDn': static_path}
+
+ if interface_mode is not None:
+ interface_mode = INTERFACE_MODE_MAPPING[interface_mode]
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvAp',
+ aci_rn='ap-{0}'.format(ap),
+ module_object=ap,
+ target_filter={'name': ap},
+ ),
+ subclass_2=dict(
+ aci_class='fvAEPg',
+ aci_rn='epg-{0}'.format(epg),
+ module_object=epg,
+ target_filter={'name': epg},
+ ),
+ subclass_3=dict(
+ aci_class='fvRsPathAtt',
+ aci_rn='rspathAtt-[{0}]'.format(static_path),
+ module_object=static_path,
+ target_filter=path_target_filter,
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvRsPathAtt',
+ class_config=dict(
+ descr=description,
+ encap=encap_id,
+ primaryEncap=primary_encap_id,
+ instrImedcy=deploy_immediacy,
+ mode=interface_mode,
+ tDn=static_path,
+ ),
+ )
+
+ aci.get_diff(aci_class='fvRsPathAtt')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py
new file mode 100644
index 00000000..0334fd84
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_leaf_selector.py
@@ -0,0 +1,349 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_switch_leaf_selector
+short_description: Bind leaf selectors to switch policy leaf profiles (infra:LeafS, infra:NodeBlk, infra:RsAccNodePGrep)
+description:
+- Bind leaf selectors (with node block range and policy group) to switch policy leaf profiles on Cisco ACI fabrics.
+options:
+ description:
+ description:
+ - The description to assign to the C(leaf).
+ type: str
+ leaf_profile:
+ description:
+ - Name of the Leaf Profile to which we add a Selector.
+ type: str
+ aliases: [ leaf_profile_name ]
+ leaf:
+ description:
+ - Name of Leaf Selector.
+ type: str
+ aliases: [ name, leaf_name, leaf_profile_leaf_name, leaf_selector_name ]
+ leaf_node_blk:
+ description:
+ - Name of Node Block range to be added to Leaf Selector of given Leaf Profile.
+ type: str
+ aliases: [ leaf_node_blk_name, node_blk_name ]
+ leaf_node_blk_description:
+ description:
+ - The description to assign to the C(leaf_node_blk)
+ type: str
+ from:
+ description:
+ - Start of Node Block range.
+ type: int
+ aliases: [ node_blk_range_from, from_range, range_from ]
+ to:
+ description:
+ - Start of Node Block range.
+ type: int
+ aliases: [ node_blk_range_to, to_range, range_to ]
+ policy_group:
+ description:
+ - Name of the Policy Group to be added to Leaf Selector of given Leaf Profile.
+ type: str
+ aliases: [ name, policy_group_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- This module is to be used with M(cisco.aci.aci_switch_policy_leaf_profile).
+ One first creates a leaf profile (infra:NodeP) and then creates an associated selector (infra:LeafS),
+seealso:
+- module: cisco.aci.aci_switch_policy_leaf_profile
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(infra:LeafS),
+ B(infra:NodeBlk) and B(infra:RsAccNodePGrp).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+'''
+
+EXAMPLES = r'''
+- name: adding a switch policy leaf profile selector associated Node Block range (w/ policy group)
+ cisco.aci.aci_switch_leaf_selector:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ leaf: leaf_selector_name
+ leaf_node_blk: node_blk_name
+ from: 1011
+ to: 1011
+ policy_group: somepolicygroupname
+ state: present
+ delegate_to: localhost
+
+- name: adding a switch policy leaf profile selector associated Node Block range (w/o policy group)
+ cisco.aci.aci_switch_leaf_selector:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ leaf: leaf_selector_name
+ leaf_node_blk: node_blk_name
+ from: 1011
+ to: 1011
+ state: present
+ delegate_to: localhost
+
+- name: Removing a switch policy leaf profile selector
+ cisco.aci.aci_switch_leaf_selector:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ leaf: leaf_selector_name
+ state: absent
+ delegate_to: localhost
+
+- name: Querying a switch policy leaf profile selector
+ cisco.aci.aci_switch_leaf_selector:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ leaf: leaf_selector_name
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update({
+ 'description': dict(type='str'),
+ 'leaf_profile': dict(type='str', aliases=['leaf_profile_name']), # Not required for querying all objects
+ 'leaf': dict(type='str', aliases=['name', 'leaf_name', 'leaf_profile_leaf_name', 'leaf_selector_name']), # Not required for querying all objects
+ 'leaf_node_blk': dict(type='str', aliases=['leaf_node_blk_name', 'node_blk_name']),
+ 'leaf_node_blk_description': dict(type='str'),
+ # NOTE: Keyword 'from' is a reserved word in python, so we need it as a string
+ 'from': dict(type='int', aliases=['node_blk_range_from', 'from_range', 'range_from']),
+ 'to': dict(type='int', aliases=['node_blk_range_to', 'to_range', 'range_to']),
+ 'policy_group': dict(type='str', aliases=['policy_group_name']),
+ 'state': dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ 'name_alias': dict(type='str'),
+ })
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['leaf_profile', 'leaf']],
+ ['state', 'present', ['leaf_profile', 'leaf', 'leaf_node_blk', 'from', 'to']]
+ ]
+ )
+
+ description = module.params.get('description')
+ leaf_profile = module.params.get('leaf_profile')
+ leaf = module.params.get('leaf')
+ leaf_node_blk = module.params.get('leaf_node_blk')
+ leaf_node_blk_description = module.params.get('leaf_node_blk_description')
+ from_ = module.params.get('from')
+ to_ = module.params.get('to')
+ policy_group = module.params.get('policy_group')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ # Build child_configs dynamically
+ child_configs = [
+ dict(
+ infraNodeBlk=dict(
+ attributes=dict(
+ descr=leaf_node_blk_description,
+ name=leaf_node_blk,
+ from_=from_,
+ to_=to_,
+ ),
+ ),
+ ),
+ ]
+
+ # Add infraRsAccNodePGrp only when policy_group was defined
+ if policy_group is not None:
+ child_configs.append(dict(
+ infraRsAccNodePGrp=dict(
+ attributes=dict(
+ tDn='uni/infra/funcprof/accnodepgrp-{0}'.format(policy_group),
+ ),
+ ),
+ ))
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='infraNodeP',
+ aci_rn='infra/nprof-{0}'.format(leaf_profile),
+ module_object=leaf_profile,
+ target_filter={'name': leaf_profile},
+ ),
+ subclass_1=dict(
+ aci_class='infraLeafS',
+ # NOTE: normal rn: leaves-{name}-typ-{type}, hence here hardcoded to range for purposes of module
+ aci_rn='leaves-{0}-typ-range'.format(leaf),
+ module_object=leaf,
+ target_filter={'name': leaf},
+ ),
+ # NOTE: infraNodeBlk is not made into a subclass because there is a 1-1 mapping between node block and leaf selector name
+ child_classes=['infraNodeBlk', 'infraRsAccNodePGrp'],
+
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraLeafS',
+ class_config=dict(
+ descr=description,
+ name=leaf,
+ nameAlias=name_alias,
+ ),
+ child_configs=child_configs,
+ )
+
+ aci.get_diff(aci_class='infraLeafS')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_leaf_profile.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_leaf_profile.py
new file mode 100644
index 00000000..932a0d8b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_leaf_profile.py
@@ -0,0 +1,250 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_switch_policy_leaf_profile
+short_description: Manage switch policy leaf profiles (infra:NodeP)
+description:
+- Manage switch policy leaf profiles on Cisco ACI fabrics.
+options:
+ leaf_profile:
+ description:
+ - The name of the Leaf Profile.
+ type: str
+ aliases: [ leaf_profile_name, name ]
+ description:
+ description:
+ - Description for the Leaf Profile.
+ type: str
+ aliases: [ descr ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_switch_policy_leaf_profile
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(infra:NodeP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+'''
+
+EXAMPLES = r'''
+- name: creating a Leaf Profile with description
+ cisco.aci.aci_switch_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ description: sw_description
+ state: present
+ delegate_to: localhost
+
+- name: Deleting a Leaf Profile
+ cisco.aci.aci_switch_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ state: absent
+ delegate_to: localhost
+
+- name: Query a Leaf Profile
+ cisco.aci.aci_switch_policy_leaf_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ leaf_profile: sw_name
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ leaf_profile=dict(type='str', aliases=['name', 'leaf_profile_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['leaf_profile']],
+ ['state', 'present', ['leaf_profile']],
+ ],
+ )
+
+ leaf_profile = module.params.get('leaf_profile')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='infraNodeP',
+ aci_rn='infra/nprof-{0}'.format(leaf_profile),
+ module_object=leaf_profile,
+ target_filter={'name': leaf_profile},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='infraNodeP',
+ class_config=dict(
+ name=leaf_profile,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='infraNodeP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py
new file mode 100644
index 00000000..184f20dd
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_switch_policy_vpc_protection_group.py
@@ -0,0 +1,304 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_switch_policy_vpc_protection_group
+short_description: Manage switch policy explicit vPC protection groups (fabric:ExplicitGEp, fabric:NodePEp).
+description:
+- Manage switch policy explicit vPC protection groups on Cisco ACI fabrics.
+options:
+ protection_group:
+ description:
+ - The name of the Explicit vPC Protection Group.
+ type: str
+ aliases: [ name, protection_group_name ]
+ protection_group_id:
+ description:
+ - The Explicit vPC Protection Group ID.
+ type: int
+ aliases: [ id ]
+ vpc_domain_policy:
+ description:
+ - The vPC domain policy to be associated with the Explicit vPC Protection Group.
+ type: str
+ aliases: [ vpc_domain_policy_name ]
+ switch_1_id:
+ description:
+ - The ID of the first Leaf Switch for the Explicit vPC Protection Group.
+ type: int
+ switch_2_id:
+ description:
+ - The ID of the Second Leaf Switch for the Explicit vPC Protection Group.
+ type: int
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_switch_policy_leaf_profile
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(fabric:ExplicitGEp) and B(fabric:NodePEp).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Bruno Calogero (@brunocalogero)
+'''
+
+EXAMPLES = r'''
+- name: Add vPC Protection Group
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ protection_group: leafPair101-vpcGrp
+ protection_group_id: 6
+ switch_1_id: 1011
+ switch_2_id: 1012
+ state: present
+ delegate_to: localhost
+
+- name: Remove Explicit vPC Protection Group
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ protection_group: leafPair101-vpcGrp
+ state: absent
+ delegate_to: localhost
+
+- name: Query vPC Protection Groups
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query our vPC Protection Group
+ cisco.aci.aci_switch_policy_vpc_protection_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ protection_group: leafPair101-vpcGrp
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ protection_group=dict(type='str', aliases=['name', 'protection_group_name']), # Not required for querying all objects
+ protection_group_id=dict(type='int', aliases=['id']),
+ vpc_domain_policy=dict(type='str', aliases=['vpc_domain_policy_name']),
+ switch_1_id=dict(type='int'),
+ switch_2_id=dict(type='int'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['protection_group']],
+ ['state', 'present', ['protection_group', 'protection_group_id', 'switch_1_id', 'switch_2_id']],
+ ],
+ )
+
+ protection_group = module.params.get('protection_group')
+ protection_group_id = module.params.get('protection_group_id')
+ vpc_domain_policy = module.params.get('vpc_domain_policy')
+ switch_1_id = module.params.get('switch_1_id')
+ switch_2_id = module.params.get('switch_2_id')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fabricExplicitGEp',
+ aci_rn='fabric/protpol/expgep-{0}'.format(protection_group),
+ module_object=protection_group,
+ target_filter={'name': protection_group},
+ ),
+ child_classes=['fabricNodePEp', 'fabricNodePEp', 'fabricRsVpcInstPol'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fabricExplicitGEp',
+ class_config=dict(
+ name=protection_group,
+ id=protection_group_id,
+ nameAlias=name_alias,
+ ),
+ child_configs=[
+ dict(
+ fabricNodePEp=dict(
+ attributes=dict(
+ id='{0}'.format(switch_1_id),
+ ),
+ ),
+ ),
+ dict(
+ fabricNodePEp=dict(
+ attributes=dict(
+ id='{0}'.format(switch_2_id),
+ ),
+ ),
+ ),
+ dict(
+ fabricRsVpcInstPol=dict(
+ attributes=dict(
+ tnVpcInstPolName=vpc_domain_policy,
+ ),
+ ),
+ ),
+ ],
+ )
+
+ aci.get_diff(aci_class='fabricExplicitGEp')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_system.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_system.py
new file mode 100644
index 00000000..b4789adc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_system.py
@@ -0,0 +1,197 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = r'''
+---
+module: aci_system
+short_description: Query the ACI system information (top:System)
+description:
+- Query the ACI system information (top:System) on Cisco ACI.
+author:
+- Lionel Hercot (@lhercot)
+options:
+ id:
+ description:
+ - The controller node ID
+ aliases: [ controller, node ]
+ type: int
+ state:
+ description:
+ - Use C(query) for listing an object or multiple objects.
+ choices: [ query ]
+ default: query
+ type: str
+notes:
+- More information about the internal APIC class B(top:System) from
+ L(the APIC Management Information Model reference,https://developer.cisco.com/docs/apic-mim-ref/).
+- This module is used to query system information for both cloud and on-premises controllers.
+
+extends_documentation_fragment:
+- cisco.aci.aci
+'''
+
+EXAMPLES = r'''
+- name: Query all controllers system information
+ cisco.aci.aci_system:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ state: query
+ delegate_to: localhost
+
+- name: Query controller 1 specific system information
+ cisco.aci.aci_system:
+ host: apic
+ username: userName
+ password: somePassword
+ validate_certs: no
+ id: 1
+ state: query
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+from ansible.module_utils.basic import AnsibleModule
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ id=dict(type='int', aliases=['controller', 'node']),
+ state=dict(type='str', default='query', choices=['query']),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ )
+
+ id = module.params.get('id')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='topSystem',
+ target_filter={'id': id}
+ )
+ )
+
+ aci.get_existing()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_taboo_contract.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_taboo_contract.py
new file mode 100644
index 00000000..b730328c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_taboo_contract.py
@@ -0,0 +1,286 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_taboo_contract
+short_description: Manage taboo contracts (vz:BrCP)
+description:
+- Manage taboo contracts on Cisco ACI fabrics.
+options:
+ taboo_contract:
+ description:
+ - The name of the Taboo Contract.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description for the Taboo Contract.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ scope:
+ description:
+ - The scope of a service contract.
+ - The APIC defaults to C(context) when unset during creation.
+ type: str
+ choices: [ application-profile, context, global, tenant ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(vz:BrCP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add taboo contract
+ cisco.aci.aci_taboo_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: ansible_test
+ taboo_contract: taboo_contract_test
+ state: present
+ delegate_to: localhost
+
+- name: Remove taboo contract
+ cisco.aci.aci_taboo_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: ansible_test
+ taboo_contract: taboo_contract_test
+ state: absent
+ delegate_to: localhost
+
+- name: Query all taboo contracts
+ cisco.aci.aci_taboo_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a specific taboo contract
+ cisco.aci.aci_taboo_contract:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: ansible_test
+ taboo_contract: taboo_contract_test
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ taboo_contract=dict(type='str', aliases=['name']), # Not required for querying all contracts
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all contracts
+ scope=dict(type='str', choices=['application-profile', 'context', 'global', 'tenant']),
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['tenant', 'taboo_contract']],
+ ['state', 'present', ['tenant', 'taboo_contract']],
+ ],
+ )
+
+ taboo_contract = module.params.get('taboo_contract')
+ description = module.params.get('description')
+ scope = module.params.get('scope')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='vzTaboo',
+ aci_rn='taboo-{0}'.format(taboo_contract),
+ module_object=taboo_contract,
+ target_filter={'name': taboo_contract},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='vzTaboo',
+ class_config=dict(
+ name=taboo_contract,
+ descr=description,
+ scope=scope,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='vzTaboo')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant.py
new file mode 100644
index 00000000..26ee14cf
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant.py
@@ -0,0 +1,261 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_tenant
+short_description: Manage tenants (fv:Tenant)
+description:
+- Manage tenants on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ name, tenant_name ]
+ description:
+ description:
+ - Description for the tenant.
+ type: str
+ aliases: [ descr ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_ap
+- module: cisco.aci.aci_bd
+- module: cisco.aci.aci_contract
+- module: cisco.aci.aci_filter
+- module: cisco.aci.aci_vrf
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:Tenant).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Add a new tenant
+ cisco.aci.aci_tenant:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ description: Production tenant
+ state: present
+ delegate_to: localhost
+
+- name: Remove a tenant
+ cisco.aci.aci_tenant:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ state: absent
+ delegate_to: localhost
+
+- name: Query a tenant
+ cisco.aci.aci_tenant:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all tenants
+ cisco.aci.aci_tenant:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['name', 'tenant_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['tenant']],
+ ['state', 'present', ['tenant']],
+ ],
+ )
+
+ description = module.params.get('description')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ )
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvTenant',
+ class_config=dict(
+ name=tenant,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='fvTenant')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py
new file mode 100644
index 00000000..ca8393d2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_action_rule_profile.py
@@ -0,0 +1,246 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_tenant_action_rule_profile
+short_description: Manage action rule profiles (rtctrl:AttrP)
+description:
+- Manage action rule profiles on Cisco ACI fabrics.
+options:
+ action_rule:
+ description:
+ - The name of the action rule profile.
+ type: str
+ aliases: [ action_rule_name, name ]
+ description:
+ description:
+ - The description for the action rule profile.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(rtctrl:AttrP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- cisco.aci.aci_tenant_action_rule_profile:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ action_rule: '{{ action_rule }}'
+ description: '{{ descr }}'
+ tenant: '{{ tenant }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ action_rule=dict(type='str', aliases=['action_rule_name', 'name']), # Not required for querying all objects
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['action_rule', 'tenant']],
+ ['state', 'present', ['action_rule', 'tenant']],
+ ],
+ )
+
+ action_rule = module.params.get('action_rule')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='rtctrlAttrP',
+ aci_rn='attr-{0}'.format(action_rule),
+ module_object=action_rule,
+ target_filter={'name': action_rule},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='rtctrlAttrP',
+ class_config=dict(
+ name=action_rule,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='rtctrlAttrP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_ep_retention_policy.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_ep_retention_policy.py
new file mode 100644
index 00000000..5b0e0e70
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_ep_retention_policy.py
@@ -0,0 +1,361 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_tenant_ep_retention_policy
+short_description: Manage End Point (EP) retention protocol policies (fv:EpRetPol)
+description:
+- Manage End Point (EP) retention protocol policies on Cisco ACI fabrics.
+options:
+ tenant:
+ description:
+ - The name of an existing tenant.
+ type: str
+ aliases: [ tenant_name ]
+ epr_policy:
+ description:
+ - The name of the end point retention policy.
+ type: str
+ aliases: [ epr_name, name ]
+ bounce_age:
+ description:
+ - Bounce entry aging interval in seconds.
+ - Accepted values range between C(150) and C(65535); 0 is used for infinite.
+ - The APIC defaults to C(630) when unset during creation.
+ type: int
+ bounce_trigger:
+ description:
+ - Determines if the bounce entries are installed by RARP Flood or COOP Protocol.
+ - The APIC defaults to C(coop) when unset during creation.
+ type: str
+ choices: [ coop, flood ]
+ hold_interval:
+ description:
+ - Hold interval in seconds.
+ - Accepted values range between C(5) and C(65535).
+ - The APIC defaults to C(300) when unset during creation.
+ type: int
+ local_ep_interval:
+ description:
+ - Local end point aging interval in seconds.
+ - Accepted values range between C(120) and C(65535); 0 is used for infinite.
+ - The APIC defaults to C(900) when unset during creation.
+ type: int
+ remote_ep_interval:
+ description:
+ - Remote end point aging interval in seconds.
+ - Accepted values range between C(120) and C(65535); 0 is used for infinite.
+ - The APIC defaults to C(300) when unset during creation.
+ type: int
+ move_frequency:
+ description:
+ - Move frequency per second.
+ - Accepted values range between C(0) and C(65535); 0 is used for none.
+ - The APIC defaults to C(256) when unset during creation.
+ type: int
+ description:
+ description:
+ - Description for the End point retention policy.
+ type: str
+ aliases: [ descr ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:EpRetPol).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Swetha Chunduri (@schunduri)
+'''
+
+EXAMPLES = r'''
+- name: Add a new EPR policy
+ cisco.aci.aci_tenant_ep_retention_policy:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ epr_policy: EPRPol1
+ bounce_age: 630
+ hold_interval: 300
+ local_ep_interval: 900
+ remote_ep_interval: 300
+ move_frequency: 256
+ description: test
+ state: present
+ delegate_to: localhost
+
+- name: Remove an EPR policy
+ cisco.aci.aci_tenant_ep_retention_policy:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ epr_policy: EPRPol1
+ state: absent
+ delegate_to: localhost
+
+- name: Query an EPR policy
+ cisco.aci.aci_tenant_ep_retention_policy:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ epr_policy: EPRPol1
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all EPR policies
+ cisco.aci.aci_tenant_ep_retention_policy:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+BOUNCE_TRIG_MAPPING = dict(
+ coop='protocol',
+ rarp='rarp-flood',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ epr_policy=dict(type='str', aliases=['epr_name', 'name']), # Not required for querying all objects
+ bounce_age=dict(type='int'),
+ bounce_trigger=dict(type='str', choices=['coop', 'flood']),
+ hold_interval=dict(type='int'),
+ local_ep_interval=dict(type='int'),
+ remote_ep_interval=dict(type='int'),
+ description=dict(type='str', aliases=['descr']),
+ move_frequency=dict(type='int'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['epr_policy', 'tenant']],
+ ['state', 'present', ['epr_policy', 'tenant']],
+ ],
+ )
+
+ epr_policy = module.params.get('epr_policy')
+ bounce_age = module.params.get('bounce_age')
+ if bounce_age is not None and bounce_age != 0 and bounce_age not in range(150, 65536):
+ module.fail_json(msg="The bounce_age must be a value of 0 or between 150 and 65535")
+ if bounce_age == 0:
+ bounce_age = 'infinite'
+ bounce_trigger = module.params.get('bounce_trigger')
+ if bounce_trigger is not None:
+ bounce_trigger = BOUNCE_TRIG_MAPPING[bounce_trigger]
+ description = module.params.get('description')
+ hold_interval = module.params.get('hold_interval')
+ if hold_interval is not None and hold_interval not in range(5, 65536):
+ module.fail_json(msg="The hold_interval must be a value between 5 and 65535")
+ local_ep_interval = module.params.get('local_ep_interval')
+ if local_ep_interval is not None and local_ep_interval != 0 and local_ep_interval not in range(120, 65536):
+ module.fail_json(msg="The local_ep_interval must be a value of 0 or between 120 and 65535")
+ if local_ep_interval == 0:
+ local_ep_interval = "infinite"
+ move_frequency = module.params.get('move_frequency')
+ if move_frequency is not None and move_frequency not in range(65536):
+ module.fail_json(msg="The move_frequency must be a value between 0 and 65535")
+ if move_frequency == 0:
+ move_frequency = "none"
+ remote_ep_interval = module.params.get('remote_ep_interval')
+ if remote_ep_interval is not None and remote_ep_interval not in range(120, 65536):
+ module.fail_json(msg="The remote_ep_interval must be a value of 0 or between 120 and 65535")
+ if remote_ep_interval == 0:
+ remote_ep_interval = "infinite"
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvEpRetPol',
+ aci_rn='epRPol-{0}'.format(epr_policy),
+ module_object=epr_policy,
+ target_filter={'name': epr_policy},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvEpRetPol',
+ class_config=dict(
+ name=epr_policy,
+ descr=description,
+ bounceAgeIntvl=bounce_age,
+ bounceTrig=bounce_trigger,
+ holdIntvl=hold_interval,
+ localEpAgeIntvl=local_ep_interval,
+ remoteEpAgeIntvl=remote_ep_interval,
+ moveFreq=move_frequency,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='fvEpRetPol')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_dst_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_dst_group.py
new file mode 100644
index 00000000..9c6c2664
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_dst_group.py
@@ -0,0 +1,246 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_tenant_span_dst_group
+short_description: Manage SPAN destination groups (span:DestGrp)
+description:
+- Manage SPAN destination groups on Cisco ACI fabrics.
+options:
+ dst_group:
+ description:
+ - The name of the SPAN destination group.
+ type: str
+ aliases: [ name ]
+ description:
+ description:
+ - The description of the SPAN destination group.
+ type: str
+ aliases: [ descr ]
+ tenant:
+ description:
+ - The name of the tenant.
+ type: str
+ aliases: [ tenant_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(span:DestGrp).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Dag Wieers (@dagwieers)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- cisco.aci.aci_tenant_span_dst_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ dst_group: '{{ dst_group }}'
+ description: '{{ descr }}'
+ tenant: '{{ tenant }}'
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ dst_group=dict(type='str', aliases=['name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['dst_group', 'tenant']],
+ ['state', 'present', ['dst_group', 'tenant']],
+ ],
+ )
+
+ dst_group = module.params.get('dst_group')
+ description = module.params.get('description')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='spanDestGrp',
+ aci_rn='destgrp-{0}'.format(dst_group),
+ module_object=dst_group,
+ target_filter={'name': dst_group},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='spanDestGrp',
+ class_config=dict(
+ name=dst_group,
+ descr=description,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='spanDestGrp')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group.py
new file mode 100644
index 00000000..0e8cbb1e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group.py
@@ -0,0 +1,265 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_tenant_span_src_group
+short_description: Manage SPAN source groups (span:SrcGrp)
+description:
+- Manage SPAN source groups on Cisco ACI fabrics.
+options:
+ admin_state:
+ description:
+ - Enable or disable the span sources.
+ - The APIC defaults to C(yes) when unset during creation.
+ type: bool
+ description:
+ description:
+ - The description for Span source group.
+ type: str
+ aliases: [ descr ]
+ dst_group:
+ description:
+ - The Span destination group to associate with the source group.
+ type: str
+ src_group:
+ description:
+ - The name of the Span source group.
+ type: str
+ aliases: [ name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ aliases: [ tenant_name ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(span:SrcGrp).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- cisco.aci.aci_tenant_span_src_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ src_group: "{{ src_group }}"
+ dst_group: "{{ dst_group }}"
+ admin_state: "{{ admin_state }}"
+ description: "{{ description }}"
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ src_group=dict(type='str', aliases=['name']), # Not required for querying all objects
+ admin_state=dict(type='bool'),
+ description=dict(type='str', aliases=['descr']),
+ dst_group=dict(type='str'),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['src_group', 'tenant']],
+ ['state', 'present', ['src_group', 'tenant']],
+ ],
+ )
+
+ aci = ACIModule(module)
+
+ admin_state = aci.boolean(module.params.get('admin_state'), 'enabled', 'disabled')
+ description = module.params.get('description')
+ dst_group = module.params.get('dst_group')
+ src_group = module.params.get('src_group')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='spanSrcGrp',
+ aci_rn='srcgrp-{0}'.format(src_group),
+ module_object=src_group,
+ target_filter={'name': src_group},
+ ),
+ child_classes=['spanSpanLbl'],
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='spanSrcGrp',
+ class_config=dict(
+ adminSt=admin_state,
+ descr=description,
+ name=src_group,
+ nameAlias=name_alias,
+ ),
+ child_configs=[{'spanSpanLbl': {'attributes': {'name': dst_group}}}],
+ )
+
+ aci.get_diff(aci_class='spanSrcGrp')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group_to_dst_group.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group_to_dst_group.py
new file mode 100644
index 00000000..c547320f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_tenant_span_src_group_to_dst_group.py
@@ -0,0 +1,260 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_tenant_span_src_group_to_dst_group
+short_description: Bind SPAN source groups to destination groups (span:SpanLbl)
+description:
+- Bind SPAN source groups to associated destination groups on Cisco ACI fabrics.
+options:
+ description:
+ description:
+ - The description for Span source group to destination group binding.
+ type: str
+ aliases: [ descr ]
+ dst_group:
+ description:
+ - The Span destination group to associate with the source group.
+ type: str
+ src_group:
+ description:
+ - The name of the Span source group.
+ type: str
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ tenant:
+ description:
+ - The name of the Tenant.
+ type: str
+ aliases: [ tenant_name ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(tenant), C(src_group), and C(dst_group) must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant), M(cisco.aci.aci_tenant_span_src_group), and M(cisco.aci.aci_tenant_span_dst_group) modules can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- module: cisco.aci.aci_tenant_span_src_group
+- module: cisco.aci.aci_tenant_span_dst_group
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(span:SrcGrp).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+# FIXME: Add more, better examples
+EXAMPLES = r'''
+- cisco.aci.aci_tenant_span_src_group_to_dst_group:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ tenant: production
+ src_group: "{{ src_group }}"
+ dst_group: "{{ dst_group }}"
+ description: "{{ description }}"
+ delegate_to: localhost
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ dst_group=dict(type='str'), # Not required for querying all objects
+ src_group=dict(type='str'), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['dst_group', 'src_group', 'tenant']],
+ ['state', 'present', ['dst_group', 'src_group', 'tenant']],
+ ],
+ )
+
+ description = module.params.get('description')
+ dst_group = module.params.get('dst_group')
+ src_group = module.params.get('src_group')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ name_alias = module.params.get('name_alias')
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='spanSrcGrp',
+ aci_rn='srcgrp-{0}'.format(src_group),
+ module_object=src_group,
+ target_filter={'name': src_group},
+ ),
+ subclass_2=dict(
+ aci_class='spanSpanLbl',
+ aci_rn='spanlbl-{0}'.format(dst_group),
+ module_object=dst_group,
+ target_filter={'name': dst_group},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='spanSpanLbl',
+ class_config=dict(
+ descr=description,
+ name=dst_group,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='spanSpanLbl')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool.py
new file mode 100644
index 00000000..542d63c6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool.py
@@ -0,0 +1,283 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_vlan_pool
+short_description: Manage VLAN pools (fvns:VlanInstP)
+description:
+- Manage VLAN pools on Cisco ACI fabrics.
+options:
+ pool_allocation_mode:
+ description:
+ - The method used for allocating VLANs to resources.
+ type: str
+ choices: [ dynamic, static]
+ aliases: [ allocation_mode, mode ]
+ description:
+ description:
+ - Description for the C(pool).
+ type: str
+ aliases: [ descr ]
+ pool:
+ description:
+ - The name of the pool.
+ type: str
+ aliases: [ name, pool_name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_encap_pool
+- module: cisco.aci.aci_vlan_pool_encap_block
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fvns:VlanInstP).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add a new VLAN pool
+ cisco.aci.aci_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_allocation_mode: dynamic
+ description: Production VLANs
+ state: present
+ delegate_to: localhost
+
+- name: Remove a VLAN pool
+ cisco.aci.aci_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_allocation_mode: dynamic
+ state: absent
+ delegate_to: localhost
+
+- name: Query a VLAN pool
+ cisco.aci.aci_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ pool_allocation_mode: dynamic
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all VLAN pools
+ cisco.aci.aci_vlan_pool:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ pool=dict(type='str', aliases=['name', 'pool_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ pool_allocation_mode=dict(type='str', aliases=['allocation_mode', 'mode'], choices=['dynamic', 'static']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['pool']],
+ ['state', 'present', ['pool']],
+ ],
+ )
+
+ description = module.params.get('description')
+ pool = module.params.get('pool')
+ pool_allocation_mode = module.params.get('pool_allocation_mode')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ pool_name = pool
+
+ # ACI Pool URL requires the allocation mode for vlan and vsan pools (ex: uni/infra/vlanns-[poolname]-static)
+ if pool is not None:
+ if pool_allocation_mode is not None:
+ pool_name = '[{0}]-{1}'.format(pool, pool_allocation_mode)
+ else:
+ module.fail_json(msg="ACI requires the 'pool_allocation_mode' when 'pool' is provided")
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvnsVlanInstP',
+ aci_rn='infra/vlanns-{0}'.format(pool_name),
+ module_object=pool,
+ target_filter={'name': pool},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvnsVlanInstP',
+ class_config=dict(
+ allocMode=pool_allocation_mode,
+ descr=description,
+ name=pool,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class='fvnsVlanInstP')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool_encap_block.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool_encap_block.py
new file mode 100644
index 00000000..e7204c63
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vlan_pool_encap_block.py
@@ -0,0 +1,362 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# 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)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_vlan_pool_encap_block
+short_description: Manage encap blocks assigned to VLAN pools (fvns:EncapBlk)
+description:
+- Manage VLAN encap blocks that are assigned to VLAN pools on Cisco ACI fabrics.
+options:
+ allocation_mode:
+ description:
+ - The method used for allocating encaps to resources.
+ type: str
+ choices: [ dynamic, inherit, static]
+ aliases: [ mode ]
+ description:
+ description:
+ - Description for the pool encap block.
+ type: str
+ aliases: [ descr ]
+ pool:
+ description:
+ - The name of the pool that the encap block should be assigned to.
+ type: str
+ aliases: [ pool_name ]
+ pool_allocation_mode:
+ description:
+ - The method used for allocating encaps to resources.
+ type: str
+ choices: [ dynamic, static]
+ aliases: [ pool_mode ]
+ block_end:
+ description:
+ - The end of encap block.
+ type: int
+ aliases: [ end ]
+ block_name:
+ description:
+ - The name to give to the encap block.
+ type: str
+ aliases: [ name ]
+ block_start:
+ description:
+ - The start of the encap block.
+ type: int
+ aliases: [ start ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+extends_documentation_fragment:
+- cisco.aci.aci
+
+notes:
+- The C(pool) must exist in order to add or delete a encap block.
+seealso:
+- module: cisco.aci.aci_encap_pool_range
+- module: cisco.aci.aci_vlan_pool
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fvns:EncapBlk).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+- Dag Wieers (@dagwieers)
+'''
+
+EXAMPLES = r'''
+- name: Add a new VLAN encap block
+ cisco.aci.aci_vlan_pool_encap_block:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ block_start: 20
+ block_end: 50
+ state: present
+ delegate_to: localhost
+
+- name: Remove a VLAN encap block
+ cisco.aci.aci_vlan_pool_encap_block:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ block_start: 20
+ block_end: 50
+ state: absent
+ delegate_to: localhost
+
+- name: Query a VLAN encap block
+ cisco.aci.aci_vlan_pool_encap_block:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ block_start: 20
+ block_end: 50
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query a VLAN pool for encap blocks
+ cisco.aci.aci_vlan_pool_encap_block:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ pool: production
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all VLAN encap blocks
+ cisco.aci.aci_vlan_pool_encap_block:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ pool=dict(type='str', aliases=['pool_name']), # Not required for querying all objects
+ block_name=dict(type='str', aliases=['name']), # Not required for querying all objects
+ block_end=dict(type='int', aliases=['end']), # Not required for querying all objects
+ block_start=dict(type='int', aliases=["start"]), # Not required for querying all objects
+ allocation_mode=dict(type='str', aliases=['mode'], choices=['dynamic', 'inherit', 'static']),
+ description=dict(type='str', aliases=['descr']),
+ pool_allocation_mode=dict(type='str', aliases=['pool_mode'], choices=['dynamic', 'static']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['pool', 'block_end', 'block_name', 'block_start']],
+ ['state', 'present', ['pool', 'block_end', 'block_name', 'block_start']],
+ ],
+ )
+
+ allocation_mode = module.params.get('allocation_mode')
+ description = module.params.get('description')
+ pool = module.params.get('pool')
+ pool_allocation_mode = module.params.get('pool_allocation_mode')
+ block_end = module.params.get('block_end')
+ block_name = module.params.get('block_name')
+ block_start = module.params.get('block_start')
+ state = module.params.get('state')
+ name_alias = module.params.get('name_alias')
+
+ if block_end is not None:
+ encap_end = 'vlan-{0}'.format(block_end)
+ else:
+ encap_end = None
+
+ if block_start is not None:
+ encap_start = 'vlan-{0}'.format(block_start)
+ else:
+ encap_start = None
+
+ # Collect proper mo information
+ aci_block_mo = 'from-[{0}]-to-[{1}]'.format(encap_start, encap_end)
+ pool_name = pool
+
+ # Validate block_end and block_start are valid for its respective encap type
+ for encap_id in block_end, block_start:
+ if encap_id is not None:
+ if not 1 <= encap_id <= 4094:
+ module.fail_json(msg="vlan pools must have 'block_start' and 'block_end' values between 1 and 4094")
+
+ if block_end is not None and block_start is not None:
+ # Validate block_start is less than block_end
+ if block_start > block_end:
+ module.fail_json(msg="The 'block_start' must be less than or equal to the 'block_end'")
+
+ elif block_end is None and block_start is None:
+ if block_name is None:
+ # Reset range managed object to None for aci util to properly handle query
+ aci_block_mo = None
+
+ # ACI Pool URL requires the allocation mode (ex: uni/infra/vlanns-[poolname]-static)
+ if pool is not None:
+ if pool_allocation_mode is not None:
+ pool_name = '[{0}]-{1}'.format(pool, pool_allocation_mode)
+ else:
+ module.fail_json(msg="ACI requires the 'pool_allocation_mode' when 'pool' is provided")
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvnsVlanInstP',
+ aci_rn='infra/vlanns-{0}'.format(pool_name),
+ module_object=pool,
+ target_filter={'name': pool},
+ ),
+ subclass_1=dict(
+ aci_class='fvnsEncapBlk',
+ aci_rn=aci_block_mo,
+ module_object=aci_block_mo,
+ target_filter={'from': encap_start, 'to': encap_end, 'name': block_name},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvnsEncapBlk',
+ class_config={
+ "allocMode": allocation_mode,
+ "descr": description,
+ "from": encap_start,
+ "name": block_name,
+ "to": encap_end,
+ "nameAlias": name_alias,
+ },
+ )
+
+ aci.get_diff(aci_class='fvnsEncapBlk')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vmm_credential.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vmm_credential.py
new file mode 100644
index 00000000..b9a8a8c7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vmm_credential.py
@@ -0,0 +1,316 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'}
+
+DOCUMENTATION = r'''
+---
+module: aci_vmm_credential
+short_description: Manage virtual domain credential profiles (vmm:UsrAccP)
+description:
+- Manage virtual domain credential profiles on Cisco ACI fabrics.
+options:
+ name:
+ description:
+ - Name of the credential profile.
+ type: str
+ aliases: [ credential_name, credential_profile ]
+ credential_password:
+ description:
+ - VMM controller password.
+ type: str
+ aliases: []
+ credential_username:
+ description:
+ - VMM controller username.
+ type: str
+ aliases: []
+ description:
+ description:
+ - Description for the tenant.
+ type: str
+ aliases: [ descr ]
+ domain:
+ description:
+ - Name of the virtual domain profile.
+ type: str
+ aliases: [ domain_name, domain_profile, name ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ vm_provider:
+ description:
+ - The VM platform for VMM Domains.
+ - Support for Kubernetes was added in ACI v3.0.
+ - Support for CloudFoundry, OpenShift and Red Hat was added in ACI v3.1.
+ type: str
+ choices: [ cloudfoundry, kubernetes, microsoft, openshift, openstack, redhat, vmware ]
+extends_documentation_fragment:
+- cisco.aci.aci
+
+seealso:
+- module: cisco.aci.aci_domain
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC classes B(vmm:DomP)
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jason Juenger (@jasonjuenger)
+'''
+
+EXAMPLES = r'''
+- name: Add credential to VMware VMM domain
+ cisco.aci.aci_vmm_credential:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: vmware_dom
+ description: secure credential
+ name: vCenterCredential
+ credential_username: vCenterUsername
+ credential_password: vCenterPassword
+ vm_provider: vmware
+ state: present
+
+- name: Remove credential from VMware VMM domain
+ cisco.aci.aci_vmm_credential:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: vmware_dom
+ name: myCredential
+ vm_provider: vmware
+ state: absent
+
+- name: Query a specific VMware VMM credential
+ cisco.aci.aci_vmm_credential:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: vmware_dom
+ name: vCenterCredential
+ vm_provider: vmware
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all VMware VMM credentials
+ cisco.aci.aci_vmm_credential:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ domain: vmware_dom
+ vm_provider: vmware
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+VM_PROVIDER_MAPPING = dict(
+ cloudfoundry='CloudFoundry',
+ kubernetes='Kubernetes',
+ microsoft='Microsoft',
+ openshift='OpenShift',
+ openstack='OpenStack',
+ redhat='Redhat',
+ vmware='VMware',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ name=dict(type='str', aliases=['credential_name', 'credential_profile']),
+ credential_password=dict(type='str', no_log=True),
+ credential_username=dict(type='str'),
+ description=dict(type='str', aliases=['descr']),
+ domain=dict(type='str', aliases=['domain_name', 'domain_profile']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ vm_provider=dict(type='str', choices=list(VM_PROVIDER_MAPPING.keys())),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['domain']],
+ ['state', 'present', ['domain']],
+ ],
+ )
+
+ name = module.params.get('name')
+ credential_password = module.params.get('credential_password')
+ credential_username = module.params.get('credential_username')
+ description = module.params.get('description')
+ domain = module.params.get('domain')
+ state = module.params.get('state')
+ vm_provider = module.params.get('vm_provider')
+ name_alias = module.params.get('name_alias')
+
+ credential_class = 'vmmUsrAccP'
+ usracc_mo = 'uni/vmmp-{0}/dom-{1}/usracc-{2}'.format(VM_PROVIDER_MAPPING.get(vm_provider), domain, name)
+ usracc_rn = 'vmmp-{0}/dom-{1}/usracc-{2}'.format(VM_PROVIDER_MAPPING.get(vm_provider), domain, name)
+
+ # Ensure that querying all objects works when only domain is provided
+ if name is None:
+ usracc_mo = None
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class=credential_class,
+ aci_rn=usracc_rn,
+ module_object=usracc_mo,
+ target_filter={'name': domain, 'usracc': name},
+ ),
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class=credential_class,
+ class_config=dict(
+ descr=description,
+ name=name,
+ pwd=credential_password,
+ usr=credential_username,
+ nameAlias=name_alias,
+ ),
+ )
+
+ aci.get_diff(aci_class=credential_class)
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vrf.py b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vrf.py
new file mode 100644
index 00000000..6bb230c2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/plugins/modules/aci_vrf.py
@@ -0,0 +1,324 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+ 'status': ['preview'],
+ 'supported_by': 'certified'}
+
+DOCUMENTATION = r'''
+---
+module: aci_vrf
+short_description: Manage contexts or VRFs (fv:Ctx)
+description:
+- Manage contexts or VRFs on Cisco ACI fabrics.
+- Each context is a private network associated to a tenant, i.e. VRF.
+- Enable Preferred Groups for VRF
+options:
+ tenant:
+ description:
+ - The name of the Tenant the VRF should belong to.
+ type: str
+ aliases: [ tenant_name ]
+ vrf:
+ description:
+ - The name of the VRF.
+ type: str
+ aliases: [ context, name, vrf_name ]
+ policy_control_direction:
+ description:
+ - Determines if the policy should be enforced by the fabric on ingress or egress.
+ type: str
+ choices: [ egress, ingress ]
+ policy_control_preference:
+ description:
+ - Determines if the fabric should enforce contract policies to allow routing and packet forwarding.
+ type: str
+ choices: [ enforced, unenforced ]
+ description:
+ description:
+ - The description for the VRF.
+ type: str
+ aliases: [ descr ]
+ state:
+ description:
+ - Use C(present) or C(absent) for adding or removing.
+ - Use C(query) for listing an object or multiple objects.
+ type: str
+ choices: [ absent, present, query ]
+ default: present
+ name_alias:
+ description:
+ - The alias for the current object. This relates to the nameAlias field in ACI.
+ type: str
+ preferred_group:
+ description:
+ - Enables preferred groups for the VRF under vzAny
+ type: str
+ choices: [enabled, disabled]
+ match_type:
+ description:
+ - Configures match type for contracts under vzAny
+ type: str
+ choices: [ all, at_least_one, at_most_one, none]
+extends_documentation_fragment:
+- cisco.aci.aci
+notes:
+- The C(tenant) used must exist before using this module in your playbook.
+ The M(cisco.aci.aci_tenant) module can be used for this.
+seealso:
+- module: cisco.aci.aci_tenant
+- name: APIC Management Information Model reference
+ description: More information about the internal APIC class B(fv:Ctx).
+ link: https://developer.cisco.com/docs/apic-mim-ref/
+author:
+- Jacob McGill (@jmcgill298)
+'''
+
+EXAMPLES = r'''
+- name: Add a new VRF to a tenant
+ cisco.aci.aci_vrf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ vrf: vrf_lab
+ tenant: lab_tenant
+ descr: Lab VRF
+ policy_control_preference: enforced
+ policy_control_direction: ingress
+ state: present
+ delegate_to: localhost
+
+- name: Remove a VRF for a tenant
+ cisco.aci.aci_vrf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ vrf: vrf_lab
+ tenant: lab_tenant
+ state: absent
+ delegate_to: localhost
+
+- name: Query a VRF of a tenant
+ cisco.aci.aci_vrf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ vrf: vrf_lab
+ tenant: lab_tenant
+ state: query
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all VRFs
+ cisco.aci.aci_vrf:
+ host: apic
+ username: admin
+ password: SomeSecretPassword
+ state: query
+ delegate_to: localhost
+ register: query_result
+'''
+
+RETURN = r'''
+current:
+ description: The existing configuration from the APIC after the module has finished
+ returned: success
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+error:
+ description: The error information as returned from the APIC
+ returned: failure
+ type: dict
+ sample:
+ {
+ "code": "122",
+ "text": "unknown managed object class foo"
+ }
+raw:
+ description: The raw output returned by the APIC REST API (xml or json)
+ returned: parse error
+ type: str
+ sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
+sent:
+ description: The actual/minimal configuration pushed to the APIC
+ returned: info
+ type: list
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment"
+ }
+ }
+ }
+previous:
+ description: The original configuration from the APIC before the module has started
+ returned: info
+ type: list
+ sample:
+ [
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production",
+ "dn": "uni/tn-production",
+ "name": "production",
+ "nameAlias": "",
+ "ownerKey": "",
+ "ownerTag": ""
+ }
+ }
+ }
+ ]
+proposed:
+ description: The assembled configuration from the user-provided parameters
+ returned: info
+ type: dict
+ sample:
+ {
+ "fvTenant": {
+ "attributes": {
+ "descr": "Production environment",
+ "name": "production"
+ }
+ }
+ }
+filter_string:
+ description: The filter string used for the request
+ returned: failure or debug
+ type: str
+ sample: ?rsp-prop-include=config-only
+method:
+ description: The HTTP method used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: POST
+response:
+ description: The HTTP response from the APIC
+ returned: failure or debug
+ type: str
+ sample: OK (30 bytes)
+status:
+ description: The HTTP status from the APIC
+ returned: failure or debug
+ type: int
+ sample: 200
+url:
+ description: The HTTP url used for the request to the APIC
+ returned: failure or debug
+ type: str
+ sample: https://10.11.12.13/api/mo/uni/tn-production.json
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec
+
+MATCH_TYPE_MAPPING = dict(
+ all='All',
+ at_least_one='AtleastOne',
+ at_most_one='AtmostOne',
+ none='None',
+)
+
+
+def main():
+ argument_spec = aci_argument_spec()
+ argument_spec.update(
+ tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
+ vrf=dict(type='str', aliases=['context', 'name', 'vrf_name']), # Not required for querying all objects
+ description=dict(type='str', aliases=['descr']),
+ policy_control_direction=dict(type='str', choices=['egress', 'ingress']),
+ policy_control_preference=dict(type='str', choices=['enforced', 'unenforced']),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
+ preferred_group=dict(type='str', choices=['enabled', 'disabled']),
+ match_type=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
+ name_alias=dict(type='str'),
+ )
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ required_if=[
+ ['state', 'absent', ['tenant', 'vrf']],
+ ['state', 'present', ['tenant', 'vrf']],
+ ],
+ )
+
+ description = module.params.get('description')
+ policy_control_direction = module.params.get('policy_control_direction')
+ policy_control_preference = module.params.get('policy_control_preference')
+ state = module.params.get('state')
+ tenant = module.params.get('tenant')
+ vrf = module.params.get('vrf')
+ name_alias = module.params.get('name_alias')
+ preferred_group = module.params.get('preferred_group')
+ match_type = module.params.get('match_type')
+
+ if match_type is not None:
+ match_type = MATCH_TYPE_MAPPING[match_type]
+
+ aci = ACIModule(module)
+ aci.construct_url(
+ root_class=dict(
+ aci_class='fvTenant',
+ aci_rn='tn-{0}'.format(tenant),
+ module_object=tenant,
+ target_filter={'name': tenant},
+ ),
+ subclass_1=dict(
+ aci_class='fvCtx',
+ aci_rn='ctx-{0}'.format(vrf),
+ module_object=vrf,
+ target_filter={'name': vrf},
+ ),
+ child_classes=['vzAny']
+ )
+
+ aci.get_existing()
+
+ if state == 'present':
+ aci.payload(
+ aci_class='fvCtx',
+ class_config=dict(
+ descr=description,
+ pcEnfDir=policy_control_direction,
+ pcEnfPref=policy_control_preference,
+ name=vrf,
+ nameAlias=name_alias,
+ ),
+ child_configs=[
+ dict(vzAny=dict(attributes=dict(prefGrMemb=preferred_group, matchT=match_type))),
+ ],
+ )
+
+ aci.get_diff(aci_class='fvCtx')
+
+ aci.post_config()
+
+ elif state == 'absent':
+ aci.delete_config()
+
+ aci.exit_json()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/.gitignore b/collections-debian-merged/ansible_collections/cisco/aci/tests/.gitignore
new file mode 100644
index 00000000..ea1472ec
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/.gitignore
@@ -0,0 +1 @@
+output/
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/inventory.networking b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/inventory.networking
new file mode 100644
index 00000000..736d93a2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/inventory.networking
@@ -0,0 +1,11 @@
+[aci]
+lh-dmz1-pod3-sim-v32 ansible_host=173.36.219.136 ansible_connection=local aci_hostname=173.36.219.136 aci_username=ansible_github_ci aci_password="jZqwpB*r9&5mx3mn8e5"
+lh-dmz1-pod3-sim-v42 ansible_host=173.36.219.68 ansible_connection=local aci_hostname=173.36.219.68 aci_username=ansible_github_ci aci_password="jZqwpB*r9&5mx3mn8e5"
+
+[aci:vars]
+aws_aci_hostname=54.176.140.90
+aws_aci_username=ansible_github_ci
+aws_aci_password=sJ94G92#8dq2hx*K4qh
+azure_aci_hostname=104.42.26.226
+azure_aci_username=ansible_github_ci
+azure_aci_password=sJ94G92#8dq2hx*K4qh \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt
new file mode 100644
index 00000000..5546336e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/network-integration.requirements.txt
@@ -0,0 +1,2 @@
+lxml
+xmljson \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/target-prefixes.network b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/target-prefixes.network
new file mode 100644
index 00000000..dc092c88
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/target-prefixes.network
@@ -0,0 +1 @@
+aci
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml
new file mode 100644
index 00000000..b3841f90
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user/tasks/main.yml
@@ -0,0 +1,235 @@
+# 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: yes
+ expiration: never
+ expires: no
+ first_name: Test
+ last_name: User
+ phone: 1-234-555-678
+ check_mode: yes
+ 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: yes
+ 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.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: yes
+ phone: 2-345-555-678
+ check_mode: yes
+ 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: yes
+ 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: yes
+ check_mode: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.crt
new file mode 100644
index 00000000..cfac5531
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.key b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin.key
new file mode 100644
index 00000000..63bb00cc
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin_invalid.key b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/admin_invalid.key
new file mode 100644
index 00000000..22f5fae4
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/openssh_rsa.key b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/openssh_rsa.key
new file mode 100644
index 00000000..0c18da5c
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_ansible.key
new file mode 100644
index 00000000..ac63a005
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.crt
new file mode 100644
index 00000000..de222350
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/pki/rsa_user.key
new file mode 100644
index 00000000..354dbbdb
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml
new file mode 100644
index 00000000..78053d38
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aaa_user_certificate/tasks/main.yml
@@ -0,0 +1,279 @@
+# 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: Making sure running 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 }}'
+ certificate_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 }}'
+ certificate_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 }}'
+ certificate_name: admin
+ certificate: "{{ lookup('file', 'pki/admin.crt') }}"
+ state: present
+ check_mode: yes
+ 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: yes
+ 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
+ - 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
+ certificate_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
+ certificate_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 }}'
+ #password: '{{ aci_password }}'
+ 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: yes
+ 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'
+ 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
+ certificate_name: admin
+ check_mode: yes
+ register: cm_query_cert
+
+- name: Query our certificate using signature-based authentication (normal mode)
+ cisco.aci.aci_aaa_user_certificate:
+ <<: *cert_query
+ certificate_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'
+ certificate_name: admin
+ register: query_cert_invalid_key
+ ignore_errors: yes
+
+- 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'
+ certificate_name: admin
+ register: query_cert_invalid_key
+ ignore_errors: yes
+
+
+- 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: admin
+ register: query_cert_openssh_rsa_key
+ ignore_errors: yes
+
+- 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: "{{ item }}"
+ register: query_cert_ansible_rsa_key
+ loop:
+ - "rsa_user"
+ - "user"
+ #- "admin"
+
+- 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: "{{ item }}"
+ register: query_cert_key_content
+ loop:
+ - "rsa_user"
+ - "user"
+ #- "admin"
+
+# 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 }}'
+ certificate_name: admin
+ state: absent
+ check_mode: yes
+ 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: yes
+ 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 \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml
new file mode 100644
index 00000000..d8b84168
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_block_to_access_port/tasks/main.yml
@@ -0,0 +1,254 @@
+# 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: 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: yes
+ 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.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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 00000000..b13ea6ff
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_port_to_interface_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,205 @@
+# 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: Remove Interface policy leaf profile - Cleanup
+ 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) }}'
+ 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
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_password }}"
+ validate_certs: '{{ aci_validate_certs | default(false) }}'
+ use_ssl: '{{ aci_use_ssl | default(true) }}'
+ use_proxy: '{{ aci_use_proxy | default(true) }}'
+ 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
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_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: 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
+
+# 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: yes
+ 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.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
+ 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
+ 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: 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: yes
+ 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 \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml
new file mode 100644
index 00000000..51a53e9b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_access_sub_port_block_to_access_port/tasks/main.yml
@@ -0,0 +1,141 @@
+# 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: 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: yes
+ 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.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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml
new file mode 100644
index 00000000..90e17f38
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep/tasks/main.yml
@@ -0,0 +1,331 @@
+# 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
+
+
+# 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: yes
+ 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_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: yes
+ 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 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml
new file mode 100644
index 00000000..09000b9c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_aep_to_domain/tasks/main.yml
@@ -0,0 +1,212 @@
+# 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 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: yes
+ 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
+ - 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml
new file mode 100644
index 00000000..104b620e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_ap/tasks/main.yml
@@ -0,0 +1,190 @@
+# 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: 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: anstest
+ 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: anstest
+
+- 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: yes
+ 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: yes
+ 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.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-anstest/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-anstest.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: yes
+ 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: yes
+ 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-anstest/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml
new file mode 100644
index 00000000..2d5df49b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd/tasks/main.yml
@@ -0,0 +1,213 @@
+# 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: anstest
+ 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: create bd - check mode works
+ cisco.aci.aci_bd: &aci_bd_present
+ <<: *aci_tenant_present
+ bd: anstest
+ description: Ansible Test
+ check_mode: yes
+ 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
+ ip_learning: "no"
+ l2_unknown_unicast: flood
+ l3_unknown_multicast: opt-flood
+ multi_dest: drop
+ enable_routing: "no"
+ arp_flooding: "yes"
+ register: bd_present_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: yes
+ register: bd_present_missing_param
+
+- name: present asserts
+ 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_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_missing_param is failed
+ - 'bd_present_missing_param.msg == "state is present but all of the following are missing: tenant"'
+
+- 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: anstest
+ 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,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,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_tenant.filter_string'
+ - '"tn-anstest.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,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,fvRsBdToEpRet,fvRsCtx,fvRsIgmpsn" in query_bd.filter_string'
+ - '"tn-anstest/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: yes
+ 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
+ name: anstest2
+
+- name: delete bd missing param - fails properly
+ cisco.aci.aci_bd:
+ <<: *aci_bd_absent
+ bd: "{{ fakevar | default(omit) }}"
+ ignore_errors: yes
+ 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 tenant - cleanup before ending tests
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present is changed
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml
new file mode 100644
index 00000000..8e753180
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_dhcp_label/tasks/main.yml
@@ -0,0 +1,147 @@
+# 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: 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: yes
+ 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'
+
+- 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml
new file mode 100644
index 00000000..a1545393
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_bd_subnet/tasks/main.yml
@@ -0,0 +1,240 @@
+# 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: anstest
+ 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: yes
+ 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: yes
+
+- 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: yes
+
+- 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.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: anstest
+ 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-anstest.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-anstest/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-anstest.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-anstest/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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml
new file mode 100644
index 00000000..7f287d17
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_cidr/tasks/main.yml
@@ -0,0 +1,303 @@
+# 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: '{{ aws_aci_hostname }}'
+ username: '{{ aws_aci_username }}'
+ password: '{{ aws_aci_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: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: anstest
+ register: tenant_absent
+
+- name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: anstest
+ register: tenant_present
+
+- name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: anstest
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+
+- name: Create aci cloud context profile
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ tenant: anstest
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: us-east-1
+ primary_cidr: '10.10.0.0/16'
+ cloud: aws
+ state: present
+ register: nm_add_aci_ctx_profile
+
+- name: Create non_primary CIDR (check_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ address: 10.0.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ check_mode: yes
+ register: cm_non_primary_cidr
+
+- name: Create non_primary CIDR (normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ 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-anstest/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.addr == "10.0.0.0/16"
+ - nm_non_primary_cidr.current.0.cloudCidr.attributes.dn == "uni/tn-anstest/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: anstest
+ 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-anstest/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-anstest/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: anstest
+ address: 10.10.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ check_mode: yes
+ register: cm_change_to_non_primary_cidr
+
+- name: Change primary CIDR to non_primary (normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ address: 10.10.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: present
+ ignore_errors: yes
+ 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-anstest/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: anstest
+ address: 10.10.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ check_mode: yes
+ register: cm_remove_primary_cidr
+
+- name: Remove primary CIDR (normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ address: 10.10.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ ignore_errors: yes
+ 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-anstest/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: anstest
+ 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-anstest/ctxprofile-ctx_profile_1/cidr-[10.18.0.0/16]"
+
+- name: Change setting of second non_primary CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ 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-anstest/ctxprofile-ctx_profile_1/cidr-[10.18.0.0/16]"
+
+- name: Query all CIDRs
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ 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.10.0.0/16"
+ - query_all.current.0.cloudCtxProfile.children.2.cloudCidr.attributes.primary == "yes"
+
+- name: Query primary CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ cloud_context_profile: ctx_profile_1
+ address: 10.10.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.10.0.0/16"
+ - query_primary.current.0.cloudCidr.attributes.dn == "uni/tn-anstest/ctxprofile-ctx_profile_1/cidr-[10.10.0.0/16]"
+ - query_primary.current.0.cloudCidr.attributes.primary == "yes"
+
+- name: Query non_primary CIDR
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ 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-anstest/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: anstest
+ cloud_context_profile: ctx_profile_1
+ address: non_exsisting
+ state: query
+ ignore_errors: yes
+ 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: anstest
+ address: 10.0.0.0/16
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ check_mode: yes
+ register: cm_remove_non_primary_cidr
+
+- name: Remove non_primary CIDR(normal_mode)
+ aci_cloud_cidr:
+ <<: *aci_info
+ tenant: anstest
+ 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-anstest/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-anstest/ctxprofile-ctx_profile_1/cidr-[10.0.0.0/16]"
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml
new file mode 100644
index 00000000..a063087d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_ctx_profile/tasks/main.yml
@@ -0,0 +1,323 @@
+# 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
+
+- name: Set cloud
+ set_fact:
+ cloud:
+ - aci_hostname: "{{aws_aci_hostname}}"
+ aci_username: "{{aws_aci_username}}"
+ aci_password: "{{aws_aci_password}}"
+ cloud_type: aws
+ region: us-east-1
+ region_2: us-west-1
+ - aci_hostname: "{{azure_aci_hostname}}"
+ aci_username: "{{azure_aci_username}}"
+ aci_password: "{{azure_aci_password}}"
+ cloud_type: azure
+ region: westus
+ region_2: westus2
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ 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: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ register: tenant_absent
+ loop: "{{cloud}}"
+
+- name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ register: tenant_present
+ loop: "{{cloud}}"
+
+- name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+ loop: "{{cloud}}"
+
+- name: Verify rm_ctx_profile_1
+ assert:
+ that:
+ - item.current == []
+ loop: "{{rm_ctx_profile_1.results}}"
+
+- name: Ensure aci cloud context profile 2 does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ name: ctx_profile_2
+ state: absent
+ register: rm_ctx_profile_2
+ loop: "{{cloud}}"
+
+- name: Verify rm_ctx_profile_2
+ assert:
+ that:
+ - item.current == []
+ loop: "{{rm_ctx_profile_2.results}}"
+
+- name: Create aci cloud context profile (check mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ cloud: "{{item.cloud_type}}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: us-east-1
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ check_mode: yes
+ register: cm_add_aci_ctx_profile
+ loop: "{{cloud}}"
+
+- name: Create aci cloud context profile (normal mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ cloud: "{{item.cloud_type}}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{item.region}}"
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile
+ loop: "{{cloud}}"
+
+- name: Verify cm_add_aci_ctx_profile
+ assert:
+ that:
+ - item is changed
+ - item.previous == []
+ - item.proposed.cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - item.proposed.cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - item.proposed.cloudCtxProfile.children[0].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - item.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - item.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.primary == "yes"
+ loop: "{{cm_add_aci_ctx_profile.results}}"
+
+- name: Verify nm_add_aci_ctx_profile
+ assert:
+ that:
+ - item is changed
+ - item.previous == []
+ - item.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - item.current[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - item.current[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - item.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - item.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+ loop: "{{nm_add_aci_ctx_profile.results}}"
+
+- name: Add aci cloud context profile again (check_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ cloud: "{{item.cloud_type}}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{item.region}}"
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ check_mode: yes
+ register: cm_add_aci_ctx_profile_again
+ loop: "{{cloud}}"
+
+- name: Verify cm_add_aci_ctx_profile_again
+ assert:
+ that:
+ - item is not changed
+ - item.previous[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - item.previous[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - item.previous[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - item.previous[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - item.previous[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+ loop: "{{cm_add_aci_ctx_profile_again.results}}"
+
+- name: Add aci cloud context profile again (normal_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ cloud: "{{item.cloud_type}}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{item.region}}"
+ primary_cidr: '10.100.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile_again
+ loop: "{{cloud}}"
+
+- name: Verify nm_add_aci_ctx_profile_again
+ assert:
+ that:
+ - item is not changed
+ - item.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - item.current[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1"
+ - item.current[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_1"
+ - item.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.100.0.0/16"
+ - item.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+ loop: "{{nm_add_aci_ctx_profile_again.results}}"
+
+- name: Add another aci cloud context profile (check_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ cloud: "{{item.cloud_type}}"
+ name: ctx_profile_2
+ vrf: ctx_profile_vrf_2
+ region: "{{item.region_2}}"
+ primary_cidr: '10.101.0.0/16'
+ description: "add ctx_profile_2"
+ state: present
+ check_mode: yes
+ register: cm_add_another_aci_ctx_profile
+ loop: "{{cloud}}"
+
+- name: Verify cm_add_another_aci_ctx_profile
+ assert:
+ that:
+ - item is changed
+ - item.previous == []
+ - item.proposed.cloudCtxProfile.attributes.name == "ctx_profile_2"
+ - item.proposed.cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_2"
+ - item.proposed.cloudCtxProfile.children[0].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_2"
+ - item.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.addr == "10.101.0.0/16"
+ - item.proposed.cloudCtxProfile.children[2].cloudCidr.attributes.primary == "yes"
+ - item.proposed.cloudCtxProfile.attributes.descr == "add ctx_profile_2"
+ loop: "{{cm_add_another_aci_ctx_profile.results}}"
+
+- name: Add another aci cloud context profile (normal_mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ cloud: "{{item.cloud_type}}"
+ name: ctx_profile_2
+ vrf: ctx_profile_vrf_2
+ region: "{{item.region_2}}"
+ primary_cidr: '10.101.0.0/16'
+ description: "add ctx_profile_2"
+ state: present
+ register: nm_add_another_aci_ctx_profile
+ loop: "{{cloud}}"
+
+- name: Verify nm_add_another_aci_ctx_profile
+ assert:
+ that:
+ - item is changed
+ - item.previous == []
+ - item.current[0].cloudCtxProfile.attributes.name == "ctx_profile_2"
+ - item.current[0].cloudCtxProfile.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_2"
+ - item.current[0].cloudCtxProfile.children[2].cloudRsToCtx.attributes.tnFvCtxName == "ctx_profile_vrf_2"
+ - item.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.addr == "10.101.0.0/16"
+ - item.current[0].cloudCtxProfile.children[0].cloudCidr.attributes.primary == "yes"
+ - item.current[0].cloudCtxProfile.attributes.descr == "add ctx_profile_2"
+ loop: "{{nm_add_another_aci_ctx_profile.results}}"
+
+- name: Query aci cloud context profile ctx_profile_1
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: query
+ register: query_aci_cloud_profile_1
+ loop: "{{cloud}}"
+
+- name: Verify query_aci_cloud_profile_1
+ assert:
+ that:
+ - item is not changed
+ - item.current[0].cloudCtxProfile.attributes.name == "ctx_profile_1"
+ - item.current[0].cloudCtxProfile.children | length == 3
+ loop: "{{query_aci_cloud_profile_1.results}}"
+
+- name: Query all aci cloud context profiles
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ state: query
+ register: query_all
+ loop: "{{cloud}}"
+
+- name: Verify query_all
+ assert:
+ that:
+ - item is not changed
+ - item.current | length == 1
+ - item.current.0.fvTenant.children | length == 2
+ loop: "{{query_all.results}}"
+
+- name: Remove aci cloud context profile
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile
+ loop: "{{cloud}}"
+
+- name: Verify rm_ctx_profile
+ assert:
+ that:
+ - item.current == []
+ - item.previous.0.cloudCtxProfile.attributes.name == "ctx_profile_1"
+ loop: "{{rm_ctx_profile.results}}" \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml
new file mode 100644
index 00000000..a69b819f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_provider/tasks/main.yml
@@ -0,0 +1,51 @@
+# 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: '{{ aws_aci_hostname }}'
+ username: '{{ aws_aci_username }}'
+ password: '{{ aws_aci_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: 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:
+ - version.current.0.topSystem.attributes.version is version('4.1', '>=')
+ - query_cloud.current | length > 0 \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml
new file mode 100644
index 00000000..6315f8c1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_region/tasks/main.yml
@@ -0,0 +1,66 @@
+# 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: '{{ aws_aci_hostname }}'
+ username: '{{ aws_aci_username }}'
+ password: '{{ aws_aci_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 all regions
+ aci_cloud_region:
+ <<: *aci_info
+ cloud: 'aws'
+ 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-aws"
+ - query_all.current.0.cloudProvP.attributes.vendor == "aws"
+ - query_all.current.0.cloudProvP.children | length > 10
+
+- name: Query a specific region
+ aci_cloud_region:
+ <<: *aci_info
+ cloud: 'aws'
+ region: eu-west-2
+ state: query
+ register: query_region
+
+- name: Verify query_region
+ assert:
+ that:
+ - query_region is not changed
+ - query_region.current.0.cloudRegion.attributes.adminSt == "unmanaged"
+ - query_region.current.0.cloudRegion.attributes.dn == "uni/clouddomp/provp-aws/region-eu-west-2"
+ - query_region.current.0.cloudRegion.attributes.name == "eu-west-2"
+
+- name: Query non_existing region
+ aci_cloud_region:
+ <<: *aci_info
+ cloud: 'aws'
+ 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 == [] \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml
new file mode 100644
index 00000000..b6b53bd9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_subnet/tasks/main.yml
@@ -0,0 +1,347 @@
+# 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
+
+- name: Set cloud
+ set_fact:
+ cloud:
+ - aci_hostname: "{{ aws_aci_hostname }}"
+ aci_username: "{{ aws_aci_username }}"
+ aci_password: "{{ aws_aci_password }}"
+ cloud_type: aws
+ cloud_region: us-west-1
+ cloud_zone: us-west-1a
+ - aci_hostname: "{{ azure_aci_hostname }}"
+ aci_username: "{{ azure_aci_username }}"
+ aci_password: "{{ azure_aci_password }}"
+ cloud_type: azure
+ cloud_region: westus
+ vnet_gateway: true
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ 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: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ register: tenant_absent
+ loop: "{{ cloud }}"
+
+- name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ register: tenant_present
+ loop: "{{ cloud }}"
+
+- name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+ loop: "{{ cloud }}"
+
+- name: Verify rm_ctx_profile_1
+ assert:
+ that:
+ - item.current == []
+ loop: "{{ rm_ctx_profile_1.results }}"
+
+- name: Create aci cloud context profile (normal mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud: "{{ item.cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ item.cloud_region }}"
+ primary_cidr: '10.50.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile
+ loop: "{{ cloud }}"
+
+- name: Create aci cloud subnet (check_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ item.cloud_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: test description
+ check_mode: yes
+ register: cm_add_subnet
+ loop: "{{ cloud }}"
+
+- name: Create aci cloud subnet (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ item.cloud_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: test description
+ register: nm_add_subnet
+ loop: "{{ cloud }}"
+
+- name: Verify cm_add_subnet
+ assert:
+ that:
+ - item is changed
+ - item.previous == []
+ - item.proposed.cloudSubnet.attributes.ip == "10.50.0.1"
+ - item.proposed.cloudSubnet.attributes.descr == "test description"
+ - item.proposed.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]"
+ loop: "{{ cm_add_subnet.results }}"
+
+- name: Create aci cloud subnet again (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ item.cloud_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: test description
+ register: nm_add_subnet_again
+ loop: "{{ cloud }}"
+
+- name: Verify nm_add_subnet_again
+ assert:
+ that:
+ - item is not changed
+ loop: "{{ nm_add_subnet_again.results }}"
+
+- name: Create another cloud subnet (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ item.cloud_zone | default(omit) }}"
+ address: 10.50.0.2
+ description: another subnet
+ register: nm_add_another_subnet
+ loop: "{{ cloud }}"
+
+- name: Verify nm_add_another_subnet
+ assert:
+ that:
+ - item is changed
+ - item.previous == []
+ - item.current.0.cloudSubnet.attributes.descr == "another subnet"
+ - item.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.2]"
+ - item.current.0.cloudSubnet.attributes.ip == "10.50.0.2"
+ - item.current.0.cloudSubnet.attributes.scope == "private"
+ - item.current.0.cloudSubnet.attributes.usage == "user"
+ loop: "{{ nm_add_another_subnet.results }}"
+
+- name: Create cloud subnet 3(normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ item.cloud_zone | default(omit) }}"
+ address: 10.50.0.3
+ name: subnet_3
+ register: nm_add_subnet_3
+ loop: "{{ cloud }}"
+
+- name: Specify subnet as VpnGateway enabled
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ item.cloud_zone | default(omit) }}"
+ address: 10.50.0.1
+ # name: subnet_1
+ description: change subnet 1
+ vnet_gateway: "{{ item.vnet_gateway | default(omit)}}"
+ #scope: public
+ register: nm_change_subnet_1
+ loop: "{{ cloud }}"
+
+# Enable vpn_gateway router in cloud ctx profile
+- name: Enable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: present
+ loop: "{{ cloud }}"
+
+# Try to disable vpn_gateway router again in cloud ctx profile
+- name: Disable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ loop: "{{ cloud }}"
+
+- name: Query all subnets
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ state: query
+ register: query_all
+ loop: "{{ cloud }}"
+
+- name: Verify query_all
+ assert:
+ that:
+ - item is not changed
+ - item.current.0.cloudCidr.attributes.addr == "10.50.0.0/16"
+ - item.current.0.cloudCidr.children | length == 3
+ loop: "{{ query_all.results }}"
+
+- name: Query a specific subnet
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ 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
+ loop: "{{ cloud }}"
+
+- name: Verify query_subnet_1
+ assert:
+ that:
+ - item is not changed
+ - item.current.0.cloudSubnet.attributes.ip == "10.50.0.1"
+ - item.current.0.cloudSubnet.attributes.scope == "private"
+ - item.current.0.cloudSubnet.attributes.dn == "uni/tn-ansible_test/ctxprofile-ctx_profile_1/cidr-[10.50.0.0/16]/subnet-[10.50.0.1]"
+ loop: "{{ query_subnet_1.results }}"
+
+- name: Remove subnet 3 (check_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ address: 10.50.0.3
+ state: absent
+ check_mode: yes
+ register: cm_remove_subnet_3
+ loop: "{{ cloud }}"
+
+- name: Verify cm_remove_subnet_3
+ assert:
+ that:
+ - item is changed
+ - item.proposed == {}
+ - item.previous.0.cloudSubnet.attributes.ip == "10.50.0.3"
+ loop: "{{ cm_remove_subnet_3.results }}"
+
+- name: Remove subnet 3 (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ 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
+ loop: "{{ cloud }}"
+
+- name: Verify nm_remove_subnet_3
+ assert:
+ that:
+ - item is changed
+ - item.current == []
+ - item.previous.0.cloudSubnet.attributes.ip == "10.50.0.3"
+ loop: "{{ nm_remove_subnet_3.results }}"
+
+- name: Remove subnet 3 again
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ 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
+ loop: "{{ cloud }}"
+
+- name: Verify nm_remove_subnet_3_again
+ assert:
+ that:
+ - item is not changed
+ - item.previous == []
+ - item.current == []
+ loop: "{{ nm_remove_subnet_3_again.results }}" \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml
new file mode 100644
index 00000000..521a683f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_vpn_gateway/tasks/main.yml
@@ -0,0 +1,157 @@
+# 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
+
+- name: Set cloud
+ set_fact:
+ cloud:
+ - aci_hostname: "{{ aws_aci_hostname }}"
+ aci_username: "{{ aws_aci_username }}"
+ aci_password: "{{ aws_aci_password }}"
+ cloud_type: aws
+ cloud_region: us-west-1
+ cloud_zone: us-west-1a
+ - aci_hostname: "{{ azure_aci_hostname }}"
+ aci_username: "{{ azure_aci_username }}"
+ aci_password: "{{ azure_aci_password }}"
+ cloud_type: azure
+ cloud_region: westus
+ vnet_gateway: true
+
+# CLEAN ENVIRONMENT
+- name: Set vars
+ set_fact:
+ aci_info: &aci_info
+ 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: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: ansible_test
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ register: tenant_absent
+ loop: "{{ cloud }}"
+
+- name: Ensure tenant exists for tests to kick off
+ aci_tenant:
+ <<: *aci_info
+ state: present
+ tenant: ansible_test
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ register: tenant_present
+ loop: "{{ cloud }}"
+
+- name: Ensure aci cloud context profile does not exists
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{item.aci_hostname}}"
+ username: "{{item.aci_username}}"
+ password: "{{item.aci_password}}"
+ tenant: ansible_test
+ name: ctx_profile_1
+ state: absent
+ register: rm_ctx_profile_1
+ loop: "{{ cloud }}"
+
+- name: Verify rm_ctx_profile_1
+ assert:
+ that:
+ - item.current == []
+ loop: "{{ rm_ctx_profile_1.results }}"
+
+- name: Create aci cloud context profile (normal mode)
+ aci_cloud_ctx_profile:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud: "{{ item.cloud_type }}"
+ name: ctx_profile_1
+ vrf: ctx_profile_vrf_1
+ region: "{{ item.cloud_region }}"
+ primary_cidr: '10.50.0.0/16'
+ state: present
+ register: nm_add_aci_ctx_profile
+ loop: "{{ cloud }}"
+
+- name: Create aci cloud subnet with VpnGateway enabled (normal_mode)
+ aci_cloud_subnet:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ cidr: '10.50.0.0/16'
+ availability_zone: "{{ item.cloud_zone | default(omit) }}"
+ address: 10.50.0.1
+ description: specify this subnet as VpnGateway router
+ vnet_gateway: "{{ item.vnet_gateway | default(omit)}}"
+ register: nm_add_subnet
+ loop: "{{ cloud }}"
+
+- name: Enable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: present
+ loop: "{{ cloud }}"
+
+- name: Disable VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: absent
+ loop: "{{ cloud }}"
+
+- name: Enable VpnGateway again
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ state: present
+ loop: "{{ cloud }}"
+
+- name: Query VpnGateway
+ aci_cloud_vpn_gateway:
+ <<: *aci_info
+ host: "{{ item.aci_hostname }}"
+ username: "{{ item.aci_username }}"
+ password: "{{ item.aci_password }}"
+ tenant: ansible_test
+ cloud_context_profile: ctx_profile_1
+ register: query_vpn_gateway
+ loop: "{{ cloud }}"
+
+- name: Verify VpnGateway
+ assert:
+ that:
+ - item is not changed
+ - item.current.0.cloudRouterP.children | length == 3
+ loop: "{{ query_vpn_gateway.results }}" \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml
new file mode 100644
index 00000000..1314d242
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_cloud_zone/tasks/main.yml
@@ -0,0 +1,90 @@
+# 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: '{{ aws_aci_hostname }}'
+ username: '{{ aws_aci_username }}'
+ password: '{{ aws_aci_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 all zones under us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: 'aws'
+ region: us-west-1
+ state: query
+ register: query_all
+
+- name: Verify query_all
+ assert:
+ that:
+ - query_all is not changed
+ - query_all.current.0.cloudRegion.attributes.name == "us-west-1"
+ - query_all.current.0.cloudRegion.children | length >= 2
+
+- name: Query a specific zone under region us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: 'aws'
+ region: us-west-1
+ zone: us-west-1a
+ state: query
+ register: query_zone_1
+
+- name: Query another specific zone under region us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: 'aws'
+ region: us-west-1
+ 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 == "us-west-1a"
+ - query_zone_1.current.0.cloudZone.attributes.dn == "uni/clouddomp/provp-aws/region-us-west-1/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-aws/region-us-west-1/zone-us-west-1b"
+
+- name: Query non_existing zone under region us-west-1
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: 'aws'
+ region: us-west-1
+ zone: non_existing
+ state: query
+ register: query_non_existing_zone
+
+- name: Query zone under non_existing region
+ aci_cloud_zone:
+ <<: *aci_info
+ cloud: 'aws'
+ region: non_existing
+ zone: us-west-1a
+ 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 == [] \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml
new file mode 100644
index 00000000..64c36d57
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_rollback/tasks/main.yml
@@ -0,0 +1,108 @@
+# 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: anstest
+
+- 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: anstest
+ register: tenant_present
+
+- name: create a new snapshot
+ cisco.aci.aci_config_snapshot:
+ <<: *create_snapshot
+
+- 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: yes
+ 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 == 'anstest'
+ - 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 == []
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml
new file mode 100644
index 00000000..e6170b32
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_config_snapshot/tasks/main.yml
@@ -0,0 +1,144 @@
+# 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
+ max_count: 10
+ include_secure: no
+ 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
+ include_secure: yes
+ 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: yes
+ 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: yes
+ 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.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"'
+
+- 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml
new file mode 100644
index 00000000..f31e2fbc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract/tasks/main.yml
@@ -0,0 +1,164 @@
+# 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: anstest
+ 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: yes
+ 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: yes
+ 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.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-anstest/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-anstest.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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml
new file mode 100644
index 00000000..f60d7ee7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject/tasks/main.yml
@@ -0,0 +1,246 @@
+# 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: anstest
+ 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: yes
+ 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: yes
+ 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_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_tenant_present
+ state: query
+ tenant: "{{ fakevar | default(omit) }}"
+ 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-anstest/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-class=vzSubj" in query_tenant_contract.filter_string'
+ - '"tn-anstest/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 == "anstest"
+ - 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=vzSubj" in query_tenant_subject.filter_string'
+ - '"tn-anstest.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=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 == "anstest"
+ - '"rsp-subtree-class=vzBrCP,vzSubj" in query_tenant.filter_string'
+ - '"tn-anstest.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=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: yes
+ 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: yes
+ 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: 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
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml
new file mode 100644
index 00000000..8448f2c9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_contract_subject_to_filter/tasks/main.yml
@@ -0,0 +1,194 @@
+# 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: anstest
+ 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: yes
+ 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: yes
+ 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_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: yes
+ 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: yes
+ 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: cleanup subject
+ cisco.aci.aci_contract_subject:
+ <<: *aci_subject_present
+ state: absent
+ when: subject_present is changed
+
+- name: cleanup contract
+ cisco.aci.aci_contract:
+ <<: *aci_contract_present
+ state: absent
+ when: contract_present is changed
+
+- name: cleanup filter
+ cisco.aci.aci_filter:
+ <<: *aci_filter_present
+ state: absent
+ when: filter_present is changed
+
+- name: cleanup filter
+ cisco.aci.aci_filter:
+ <<: *aci_filter_present_2
+ state: absent
+ when: filter_present_2 is changed
+
+- name: cleanup tenant
+ cisco.aci.aci_tenant:
+ <<: *aci_tenant_present
+ state: absent
+ when: tenant_present is changed
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml
new file mode 100644
index 00000000..abc01ac2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/fc.yml
@@ -0,0 +1,176 @@
+# 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: yes
+ 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.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: yes
+ 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
+
+
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml
new file mode 100644
index 00000000..29b46896
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l2dom.yml
@@ -0,0 +1,176 @@
+# 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: yes
+ 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.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: yes
+ 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
+
+
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml
new file mode 100644
index 00000000..16bc72d4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/l3dom.yml
@@ -0,0 +1,176 @@
+# 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: yes
+ 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.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: yes
+ 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
+
+
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/main.yml
new file mode 100644
index 00000000..be6c9712
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml
new file mode 100644
index 00000000..7478858c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/phys.yml
@@ -0,0 +1,176 @@
+# 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: yes
+ 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.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: yes
+ 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
+
+
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml
new file mode 100644
index 00000000..dde2a909
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain/tasks/vmm-vmware.yml
@@ -0,0 +1,184 @@
+# 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
+
+
+# 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
+ state: present
+ check_mode: yes
+ 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'
+
+- name: Add VMM domain again (check_mode)
+ cisco.aci.aci_domain: *domain_present
+ check_mode: yes
+ 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
+
+
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml
new file mode 100644
index 00000000..39187401
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_encap_pool/tasks/main.yml
@@ -0,0 +1,635 @@
+# 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 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 }
+
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ register: phys_missing_pool_type
+
+- name: Verify add operation
+ assert:
+ that:
+ - phys_vlan is changed
+ - fc_vsan is changed
+ - l2dom is changed
+ - l3dom is changed
+ - vmm_cloudfoundry is changed
+ - vmm_kubernetes is changed
+ - vmm_openshift is changed
+ - vmm_openstack is changed
+ - vmm_redhat is changed
+ - vmm_vmware is changed
+ - vmm_vmware_idemp is not changed
+ - 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_cloudfoundry.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - vmm_kubernetes.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'
+ - 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")
+
+# 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
+ 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_cloudfoundry.current.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - query_vmm_kubernetes.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
+ 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_cloudfoundry.previous.0.vmmDomP.children.0.infraRsVlanNs.attributes.tDn == 'uni/infra/vlanns-[test_pool]-dynamic'
+ - remove_vmm_kubernetes.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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml
new file mode 100644
index 00000000..2fb30c47
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_domain_to_vlan_pool/tasks/main.yml
@@ -0,0 +1,222 @@
+# 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 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: yes
+ 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.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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml
new file mode 100644
index 00000000..f33bfa00
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/main.yml
@@ -0,0 +1,18 @@
+# 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
+
+- 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml
new file mode 100644
index 00000000..7bd4bfd7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vlan.yml
@@ -0,0 +1,274 @@
+---
+- 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: yes
+ 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'
+
+- 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vsan.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vsan.yml
new file mode 100644
index 00000000..84681873
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml
new file mode 100644
index 00000000..10bd039b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool/tasks/vxlan.yml
@@ -0,0 +1,178 @@
+---
+- 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: yes
+ 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
+
+- 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml
new file mode 100644
index 00000000..66caef7e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/main.yml
@@ -0,0 +1,18 @@
+# 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
+
+- 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml
new file mode 100644
index 00000000..04a4f43b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vlan.yml
@@ -0,0 +1,387 @@
+- 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: yes
+ 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
+
+- 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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_name, range_start'"
+
+- name: missing required param - error message works
+ cisco.aci.aci_encap_pool_range:
+ <<: *aci_range_present
+ pool_allocation_mode: '{{ omit }}'
+ ignore_errors: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vsan.yml
new file mode 100644
index 00000000..7bdc332c
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_encap_pool_range/tasks/vxlan.yml
new file mode 100644
index 00000000..e5e30191
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml
new file mode 100644
index 00000000..9291c18f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg/tasks/main.yml
@@ -0,0 +1,187 @@
+# 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: 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: anstest
+ 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: anstest
+
+- 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
+ check_mode: yes
+ 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: yes
+ 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 is changed
+ - epg_present.sent == epg_present_check_mode.sent
+ - 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.fvRsAEPgMonPol.attributes.tnMonEPGPolName == 'check'
+ - '"tn-anstest/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: yes
+ 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: yes
+ 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: 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml
new file mode 100644
index 00000000..8af8c4b1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract/tasks/main.yml
@@ -0,0 +1,254 @@
+# 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 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: anstest
+ ap: anstest
+ epg: anstest
+ contract_type: provider
+ contract: "anstest_http"
+ state: absent
+
+- 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: anstest
+ 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
+ check_mode: yes
+ 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
+ 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: yes
+ register: missing_param_present
+
+- name: missing required param - failure message works
+ cisco.aci.aci_epg_to_contract:
+ <<: *aci_tenant_present
+ ignore_errors: yes
+ 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: yes
+ 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.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: yes
+ register: missing_required_query
+
+- name: query assertions
+ assert:
+ that:
+ - query_provide_contract is not changed
+ - query_provide_contract.current != []
+ - '"uni/tn-anstest/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-anstest/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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml
new file mode 100644
index 00000000..1f49f488
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_contract_master/tasks/main.yml
@@ -0,0 +1,202 @@
+# 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: Ensure tenant doesn't exist
+ aci_tenant:
+ <<: *aci_info
+ state: absent
+ tenant: anstest
+ register: tenant_absent
+
+- name: Ensure tenant exists for tests to kick off
+ aci_tenant: &aci_tenant_present
+ <<: *aci_info
+ state: present
+ tenant: anstest
+ 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-anstest/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-anstest/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-anstest/ap-anstest/epg-anstest_2/rssecInherited-[uni/tn-anstest/ap-anstest_2/epg-anstest_4]"
+ - query_specific_contract_master.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-anstest/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-anstest/ap-anstest/epg-anstest_2/rssecInherited-[uni/tn-anstest/ap-anstest/epg-anstest]"
+ - query_another_specific_contract_master.current.0.fvRsSecInherited.attributes.tDn == "uni/tn-anstest/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: anstest
+ register: tenant_absent \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml
new file mode 100644
index 00000000..f199675a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_epg_to_domain/tasks/main.yml
@@ -0,0 +1,279 @@
+# 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: 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: anstest
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ register: incompatible_params
+
+- 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'
+ - '"[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-anstest/ap-anstest/epg-anstest/rsdomAtt-[uni/phys-anstest]"
+
+- 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: yes
+ 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
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml
new file mode 100644
index 00000000..ad255bb1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_fabric_node/tasks/main.yml
@@ -0,0 +1,217 @@
+# 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: test
+ state: present
+ check_mode: yes
+ 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: yes
+ 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
+ # 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml
new file mode 100644
index 00000000..b5ceb56c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter/tasks/main.yml
@@ -0,0 +1,223 @@
+# 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: yes
+ register: cm_add_filter
+
+- name: Add filter again (check_mode)
+ cisco.aci.aci_filter: *filter_present
+ check_mode: yes
+ 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_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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ register: cm_remove_filter
+
+- name: Remove filter again (check_mode)
+ cisco.aci.aci_filter: *filter_absent
+ check_mode: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml
new file mode 100644
index 00000000..b69ae6c4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_filter_entry/tasks/main.yml
@@ -0,0 +1,299 @@
+# 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:
+ host: "{{ aci_hostname }}"
+ username: "{{ aci_username }}"
+ password: "{{ aci_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: anstest
+ state: absent
+
+- 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: anstest
+ 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: yes
+ 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: 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
+
+- 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: yes
+ register: present_missing_param
+
+- name: incompatable params - failure message works
+ cisco.aci.aci_filter_entry:
+ <<: *aci_entry_present
+ dst_port: 99
+ ignore_errors: yes
+ 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.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_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'
+ - 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: 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
+ 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-anstest/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 == "anstest"
+ - '"rsp-subtree-filter=eq(vzEntry.name,\"anstest\")" in query_tenant_entry.filter_string'
+ - '"rsp-subtree-class=vzEntry" in query_tenant_entry.filter_string'
+ - '"tn-anstest.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"
+ - query_tenant_filter.current.0.vzFilter.children | length == 4
+ - '"rsp-subtree-class=vzEntry" in query_tenant_filter.filter_string'
+ - '"tn-anstest/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 == "anstest"
+ - '"rsp-subtree-class=vzEntry,vzFilter" in query_tenant.filter_string'
+ - '"tn-anstest.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: delete entry - check mode works
+ cisco.aci.aci_filter_entry: &aci_entry_absent
+ <<: *aci_entry_present
+ state: absent
+ check_mode: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml
new file mode 100644
index 00000000..3195a3ff
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_firmware_source/tasks/main.yml
@@ -0,0 +1,207 @@
+# 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: yes
+ 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'
+
+- name: Add source again (check_mode)
+ aci_firmware_source: *source_present
+ check_mode: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases
new file mode 100644
index 00000000..cf765b70
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/aliases
@@ -0,0 +1 @@
+# unsupported
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml
new file mode 100644
index 00000000..92103acb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_cdp/tasks/main.yml
@@ -0,0 +1,106 @@
+# 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
+
+# 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
+
+
+- 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: no
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml
new file mode 100644
index 00000000..b0d94c18
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_breakout_port_group/tasks/main.yml
@@ -0,0 +1,162 @@
+# 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: 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: yes
+ 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"
+
+- 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml
new file mode 100644
index 00000000..3557c986
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_policy_group/tasks/main.yml
@@ -0,0 +1,453 @@
+# 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: 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: yes
+ 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_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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 00000000..9ee75c30
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,266 @@
+# 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
+
+# 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: yes
+ 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: yes
+ 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
+ - 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml
new file mode 100644
index 00000000..96b7e855
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_link_level/tasks/main.yml
@@ -0,0 +1,285 @@
+# 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
+
+# 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: yes
+ 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.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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml
new file mode 100644
index 00000000..32ac266e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_ospf/tasks/main.yml
@@ -0,0 +1,231 @@
+# 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: anstest
+ 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: anstest
+ 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: anstest
+ ospf: ansible_ospf
+ state: present
+ check_mode: yes
+ 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: yes
+ 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
+ - 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: yes
+ 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: yes
+ 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: yes
+ 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: anstest
+ state: query
+ check_mode: yes
+ 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: anstest
+ ospf: ansible_ospf
+ check_mode: yes
+ register: cm_query_ospf
+
+- name: Query our ospf
+ cisco.aci.aci_interface_policy_ospf:
+ <<: *interface_policy_ospf_query
+ tenant: anstest
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml
new file mode 100644
index 00000000..92a90d32
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_policy_port_security/tasks/main.yml
@@ -0,0 +1,171 @@
+# 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
+
+
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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_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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 00000000..d72a9ffa
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_interface_selector_to_switch_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,154 @@
+# 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: 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: yes
+ 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_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_query
+
+- name: query assertions
+ assert:
+ that:
+ - binding_query is not changed
+ - binding_query.current | length >= 1
+ - '"api/mo/uni/infra/nprof-swleafprftest/rsaccPortP-[uni/infra/accportprof-leafintprftest].json" in binding_query.url'
+
+- 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml
new file mode 100644
index 00000000..103e7034
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out/tasks/main.yml
@@ -0,0 +1,129 @@
+# 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: 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"
+
+- 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml
new file mode 100644
index 00000000..7a01fb84
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l2out_extepg/tasks/main.yml
@@ -0,0 +1,156 @@
+# 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: 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"
+
+- 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml
new file mode 100644
index 00000000..4ee94126
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extepg_to_contract/tasks/main.yml
@@ -0,0 +1,145 @@
+# 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: 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"
+
+- 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml
new file mode 100644
index 00000000..48796267
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_extsubnet/tasks/main.yml
@@ -0,0 +1,210 @@
+# 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: 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: yes
+ 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"
+ - cm_add_subnet.proposed.l3extSubnet.attributes.scope == "import-security"
+ - 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"
+
+- 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: yes
+ register: cm_change_subnet
+
+- 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
+ 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" \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml
new file mode 100644
index 00000000..db0d7a90
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_logical_interface_vpc_member/tasks/main.yml
@@ -0,0 +1,120 @@
+# 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: 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
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni/tn-ansible_tenant/out-ansible_l3out.json
+ method: post
+ content:
+ {
+ "l3extLNodeP": {
+ "attributes": {
+ "dn": "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_LNode",
+ "name": "ansible_LNode"
+ },
+ "children": [{
+ "l3extLIfP": {
+ "attributes": {
+ "name": "ansible_LInterface"
+ },
+ "children": [{
+ "l3extRsPathL3OutAtt": {
+ "attributes": {
+ "addr": "0.0.0.0",
+ "encap": "vlan-100",
+ "ifInstT": "ext-svi",
+ "tDn": "topology/pod-1/protpaths-101-102/pathep-[policy_group_one]"
+ }
+ }
+ }]
+ }
+ }]
+ }
+ }
+
+- name: Add 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: 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml
new file mode 100644
index 00000000..26864925
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_l3out_static_routes/tasks/main.yml
@@ -0,0 +1,138 @@
+# 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: 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
+ delegate_to: localhost
+
+- name: Add a new logical node
+ cisco.aci.aci_rest:
+ <<: *aci_info
+ path: /api/mo/uni/tn-ansible_tenant/out-ansible_l3out.json
+ method: post
+ content:
+ {
+ "l3extLNodeP": {
+ "attributes": {
+ "dn": "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-lNode",
+ "name": "lNode",
+ },
+ "children": [{
+ "l3extRsNodeL3OutAtt": {
+ "attributes": {
+ "rtrId": "10.1.0.1",
+ "rtrIdLoopBack": "yes",
+ "tDn": "topology/pod-1/node-101",
+ }
+ }
+ }]
+ }
+ }
+
+- name: Add static routes
+ 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: present
+ delegate_to: localhost
+
+- name: Query system information
+ aci_system:
+ <<: *aci_info
+ id: 1
+ state: query
+ register: version
+
+- name: Add static routes 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
+ delegate_to: localhost
+ 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
+ delegate_to: localhost
+ register: query_result
+
+- name: Query all relationships
+ aci_l3out_static_routes:
+ <<: *aci_info
+ tenant: production
+ state: query
+ ignore_errors: yes
+ register: query_result
+
+- name: Remove static routes
+ 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: absent
+ delegate_to: localhost
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml
new file mode 100644
index 00000000..c5c68a39
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/error_handling.yml
@@ -0,0 +1,191 @@
+# 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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"
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_inline.yml
new file mode 100644
index 00000000..dd27525f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml
new file mode 100644
index 00000000..9d1f6848
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/json_string.yml
@@ -0,0 +1,156 @@
+# 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": {
+ "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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml
new file mode 100644
index 00000000..85b50cbf
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/main.yml
@@ -0,0 +1,28 @@
+# 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
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/xml_string.yml
new file mode 100644
index 00000000..c8729177
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_inline.yml
new file mode 100644
index 00000000..d7538f9a
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_rest/tasks/yaml_string.yml
new file mode 100644
index 00000000..d7538f9a
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml
new file mode 100644
index 00000000..aa1e69dc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_static_binding_to_epg/tasks/main.yml
@@ -0,0 +1,206 @@
+# Test code for the ACI modules
+# Copyright: (c) 2017, Bruno Calogero <bcalogero@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: Ensure static path to epg is deleted for test kick off
+ cisco.aci.aci_static_binding_to_epg: &aci_static_binding_to_epg_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
+ tenant: anstest
+ ap: anstest
+ epg: anstest
+ interface_type: switch_port
+ pod: 1
+ leafs: 101
+ interface: '1/7'
+ state: absent
+
+- 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: anstest
+ 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: yes
+ 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: yes
+ register: provide_present
+
+- 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 - 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: yes
+ 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: yes
+ 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.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
+
+
+- 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-anstest/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-anstest.json" in query_all.url'
+
+
+- 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml
new file mode 100644
index 00000000..8b82411f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_leaf_selector/tasks/main.yml
@@ -0,0 +1,142 @@
+# 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: 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: yes
+ 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_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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml
new file mode 100644
index 00000000..80344aeb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_leaf_profile/tasks/main.yml
@@ -0,0 +1,213 @@
+# 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 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: yes
+ 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: yes
+ 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
+ - 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml
new file mode 100644
index 00000000..79785eae
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_switch_policy_vpc_protection_group/tasks/main.yml
@@ -0,0 +1,213 @@
+# 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: yes
+ 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: yes
+ 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
+ - 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_system/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_system/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_system/tasks/main.yml
new file mode 100644
index 00000000..483bd540
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml
new file mode 100644
index 00000000..8bcdd7d7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_taboo_contract/tasks/main.yml
@@ -0,0 +1,289 @@
+# 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: yes
+ 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'
+
+- name: Add taboo_contract again (check_mode)
+ cisco.aci.aci_taboo_contract: *taboo_contract_present
+ check_mode: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml
new file mode 100644
index 00000000..98478222
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_tenant/tasks/main.yml
@@ -0,0 +1,261 @@
+# 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
+
+
+# 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
+ check_mode: yes
+ register: cm_add_tenant
+
+- name: Add tenant (normal mode)
+ cisco.aci.aci_tenant: *tenant_present
+ register: nm_add_tenant
+
+- name: Add tenant again (check_mode)
+ cisco.aci.aci_tenant: *tenant_present
+ check_mode: yes
+ register: cm_add_tenant_again
+
+- name: Add tenant again (normal mode)
+ cisco.aci.aci_tenant: *tenant_present
+ register: 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
+ check_mode: yes
+ 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
+ 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
+ check_mode: yes
+ 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
+ register: 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: yes
+ 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: yes
+ 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: yes
+ 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'
+
+
+# REMOVE TENANT
+- name: Remove tenant (check_mode)
+ cisco.aci.aci_tenant: *tenant_absent
+ check_mode: yes
+ register: cm_remove_tenant
+
+- name: Remove tenant (normal mode)
+ cisco.aci.aci_tenant: *tenant_absent
+ register: nm_remove_tenant
+
+- name: Remove tenant again (check_mode)
+ cisco.aci.aci_tenant: *tenant_absent
+ check_mode: yes
+ register: cm_remove_tenant_again
+
+- name: Remove tenant again (normal mode)
+ cisco.aci.aci_tenant: *tenant_absent
+ register: 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.yml
new file mode 100644
index 00000000..6153f813
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/dynamic.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 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: yes
+ 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'
+
+- name: Add dynamic_vlan_pool again (check_mode)
+ cisco.aci.aci_vlan_pool: *dynamic_vlan_pool_present
+ check_mode: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml
new file mode 100644
index 00000000..e19ced38
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/main.yml
@@ -0,0 +1,15 @@
+# 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: static.yml
+ when: static is not defined or static
+
+- include_tasks: dynamic.yml
+ when: dynamic is not defined or dynamic
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool/tasks/static.yml
new file mode 100644
index 00000000..9962f095
--- /dev/null
+++ b/collections-debian-merged/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: yes
+ 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'
+
+- name: Add static_vlan_pool again (check_mode)
+ cisco.aci.aci_vlan_pool: *static_vlan_pool_present
+ check_mode: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml
new file mode 100644
index 00000000..913882e1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vlan_pool_encap_block/tasks/main.yml
@@ -0,0 +1,384 @@
+# 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: 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
+ 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
+ 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: yes
+ 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
+
+- 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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: yes
+ 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_name, block_start"'
+
+- name: Missing required param - error message works
+ cisco.aci.aci_vlan_pool_encap_block:
+ <<: *aci_encap_block_present
+ pool_allocation_mode: "{{ fake_var | default(omit) }}"
+ ignore_errors: yes
+ register: encap_block_present_allocation
+
+- name: Present assertions
+ assert:
+ that:
+ - encap_block_present_allocation is failed
+ - encap_block_present_allocation.msg == "ACI requires the 'pool_allocation_mode' when 'pool' is provided"
+
+- 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/main.yml
new file mode 100644
index 00000000..b76c4563
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml
new file mode 100644
index 00000000..c6029acd
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vmm_credential/tasks/vmware.yml
@@ -0,0 +1,250 @@
+# 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)
+
+# Remove VMM domain
+- name: Remove VMM domain (normal mode)
+ 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
+ register: nm_remove_domain
+
+# ADD VMM domain for testing
+- name: Add VMM domain (normal 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
+ 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
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_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: vmm_cred
+ description: my_new_cred
+ domain: vmm_dom
+ credential_username: myUsername
+ credential_password: mySecretPassword
+ vm_provider: vmware
+ state: absent
+ check_mode: yes
+ 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
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_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: vmm_cred
+ description: my_new_cred
+ domain: vmm_dom
+ credential_username: myUsername
+ credential_password: mySecretPassword
+ vm_provider: vmware
+ state: present
+ check_mode: yes
+ 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: yes
+ 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'
+
+# MODIFY credential
+- name: Modify vmware VMM credential (check mode)
+ cisco.aci.aci_vmm_credential: &credential_mod
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_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: vmm_cred
+ description: my_updated_descr
+ domain: vmm_dom
+ credential_username: myNewUsername
+ credential_password: myNewSecretPassword
+ vm_provider: vmware
+ state: present
+ check_mode: yes
+ 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
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_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: vmm_cred
+ domain: vmm_dom
+ vm_provider: vmware
+ state: query
+ check_mode: yes
+ 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:
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_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: 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
+ host: '{{ aci_hostname }}'
+ username: '{{ aci_username }}'
+ password: '{{ aci_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") }}'
+ vm_provider: vmware
+ state: query
+ check_mode: yes
+ 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: yes
+ 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 \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/aliases
new file mode 100644
index 00000000..209b793f
--- /dev/null
+++ b/collections-debian-merged/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/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml
new file mode 100644
index 00000000..838bb8c7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/integration/targets/aci_vrf/tasks/main.yml
@@ -0,0 +1,191 @@
+# 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: anstest
+ 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: yes
+ 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: yes
+ 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.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: anstest
+ 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 == "anstest"
+ - '"rsp-subtree-class=fvCtx" in query_tenant.filter_string'
+ - '"tn-anstest.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-anstest/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: yes
+ 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: yes
+ 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/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.10.txt b/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.10.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.10.txt
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.9.txt b/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.9.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/ignore-2.9.txt
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/requirements.txt b/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/requirements.txt
new file mode 100644
index 00000000..3e3a9669
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/sanity/requirements.txt
@@ -0,0 +1,4 @@
+packaging # needed for update-bundled and changelog
+sphinx ; python_version >= '3.5' # docs build requires python 3+
+sphinx-notfound-page ; python_version >= '3.5' # docs build requires python 3+
+straight.plugin ; python_version >= '3.5' # needed for hacking/build-ansible.py which will host changelog generation and requires python 3+
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/builtins.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/builtins.py
new file mode 100644
index 00000000..f60ee678
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/builtins.py
@@ -0,0 +1,33 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+#
+# Compat for python2.7
+#
+
+# One unittest needs to import builtins via __import__() so we need to have
+# the string that represents it
+try:
+ import __builtin__
+except ImportError:
+ BUILTINS = 'builtins'
+else:
+ BUILTINS = '__builtin__'
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/mock.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/mock.py
new file mode 100644
index 00000000..0972cd2e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/mock.py
@@ -0,0 +1,122 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python3.x's unittest.mock module
+'''
+import sys
+
+# Python 2.7
+
+# Note: Could use the pypi mock library on python3.x as well as python2.x. It
+# is the same as the python3 stdlib mock library
+
+try:
+ # Allow wildcard import because we really do want to import all of mock's
+ # symbols into this compat shim
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ from unittest.mock import *
+except ImportError:
+ # Python 2
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ try:
+ from mock import *
+ except ImportError:
+ print('You need the mock library installed on python2.x to run tests')
+
+
+# Prior to 3.4.4, mock_open cannot handle binary read_data
+if sys.version_info >= (3,) and sys.version_info < (3, 4, 4):
+ file_spec = None
+
+ def _iterate_read_data(read_data):
+ # Helper for mock_open:
+ # Retrieve lines from read_data via a generator so that separate calls to
+ # readline, read, and readlines are properly interleaved
+ sep = b'\n' if isinstance(read_data, bytes) else '\n'
+ data_as_list = [l + sep for l in read_data.split(sep)]
+
+ if data_as_list[-1] == sep:
+ # If the last line ended in a newline, the list comprehension will have an
+ # extra entry that's just a newline. Remove this.
+ data_as_list = data_as_list[:-1]
+ else:
+ # If there wasn't an extra newline by itself, then the file being
+ # emulated doesn't have a newline to end the last line remove the
+ # newline that our naive format() added
+ data_as_list[-1] = data_as_list[-1][:-1]
+
+ for line in data_as_list:
+ yield line
+
+ def mock_open(mock=None, read_data=''):
+ """
+ A helper function to create a mock to replace the use of `open`. It works
+ for `open` called directly or used as a context manager.
+
+ The `mock` argument is the mock object to configure. If `None` (the
+ default) then a `MagicMock` will be created for you, with the API limited
+ to methods or attributes available on standard file handles.
+
+ `read_data` is a string for the `read` methoddline`, and `readlines` of the
+ file handle to return. This is an empty string by default.
+ """
+ def _readlines_side_effect(*args, **kwargs):
+ if handle.readlines.return_value is not None:
+ return handle.readlines.return_value
+ return list(_data)
+
+ def _read_side_effect(*args, **kwargs):
+ if handle.read.return_value is not None:
+ return handle.read.return_value
+ return type(read_data)().join(_data)
+
+ def _readline_side_effect():
+ if handle.readline.return_value is not None:
+ while True:
+ yield handle.readline.return_value
+ for line in _data:
+ yield line
+
+ global file_spec
+ if file_spec is None:
+ import _io
+ file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
+
+ if mock is None:
+ mock = MagicMock(name='open', spec=open)
+
+ handle = MagicMock(spec=file_spec)
+ handle.__enter__.return_value = handle
+
+ _data = _iterate_read_data(read_data)
+
+ handle.write.return_value = None
+ handle.read.return_value = None
+ handle.readline.return_value = None
+ handle.readlines.return_value = None
+
+ handle.read.side_effect = _read_side_effect
+ handle.readline.side_effect = _readline_side_effect()
+ handle.readlines.side_effect = _readlines_side_effect
+
+ mock.return_value = handle
+ return mock
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/unittest.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/unittest.py
new file mode 100644
index 00000000..98f08ad6
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/compat/unittest.py
@@ -0,0 +1,38 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python2.7's unittest module
+'''
+
+import sys
+
+# Allow wildcard import because we really do want to import all of
+# unittests's symbols into this compat shim
+# pylint: disable=wildcard-import,unused-wildcard-import
+if sys.version_info < (2, 7):
+ try:
+ # Need unittest2 on python2.6
+ from unittest2 import *
+ except ImportError:
+ print('You need unittest2 installed on python2.6.x to run tests')
+else:
+ from unittest import *
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/loader.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/loader.py
new file mode 100644
index 00000000..0ee47fbb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/loader.py
@@ -0,0 +1,116 @@
+# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+
+from ansible.errors import AnsibleParserError
+from ansible.parsing.dataloader import DataLoader
+from ansible.module_utils._text import to_bytes, to_text
+
+
+class DictDataLoader(DataLoader):
+
+ def __init__(self, file_mapping=None):
+ file_mapping = {} if file_mapping is None else file_mapping
+ assert type(file_mapping) == dict
+
+ super(DictDataLoader, self).__init__()
+
+ self._file_mapping = file_mapping
+ self._build_known_directories()
+ self._vault_secrets = None
+
+ def load_from_file(self, path, cache=True, unsafe=False):
+ path = to_text(path)
+ if path in self._file_mapping:
+ return self.load(self._file_mapping[path], path)
+ return None
+
+ # TODO: the real _get_file_contents returns a bytestring, so we actually convert the
+ # unicode/text it's created with to utf-8
+ def _get_file_contents(self, path):
+ path = to_text(path)
+ if path in self._file_mapping:
+ return (to_bytes(self._file_mapping[path]), False)
+ else:
+ raise AnsibleParserError("file not found: %s" % path)
+
+ def path_exists(self, path):
+ path = to_text(path)
+ return path in self._file_mapping or path in self._known_directories
+
+ def is_file(self, path):
+ path = to_text(path)
+ return path in self._file_mapping
+
+ def is_directory(self, path):
+ path = to_text(path)
+ return path in self._known_directories
+
+ def list_directory(self, path):
+ ret = []
+ path = to_text(path)
+ for x in (list(self._file_mapping.keys()) + self._known_directories):
+ if x.startswith(path):
+ if os.path.dirname(x) == path:
+ ret.append(os.path.basename(x))
+ return ret
+
+ def is_executable(self, path):
+ # FIXME: figure out a way to make paths return true for this
+ return False
+
+ def _add_known_directory(self, directory):
+ if directory not in self._known_directories:
+ self._known_directories.append(directory)
+
+ def _build_known_directories(self):
+ self._known_directories = []
+ for path in self._file_mapping:
+ dirname = os.path.dirname(path)
+ while dirname not in ('/', ''):
+ self._add_known_directory(dirname)
+ dirname = os.path.dirname(dirname)
+
+ def push(self, path, content):
+ rebuild_dirs = False
+ if path not in self._file_mapping:
+ rebuild_dirs = True
+
+ self._file_mapping[path] = content
+
+ if rebuild_dirs:
+ self._build_known_directories()
+
+ def pop(self, path):
+ if path in self._file_mapping:
+ del self._file_mapping[path]
+ self._build_known_directories()
+
+ def clear(self):
+ self._file_mapping = dict()
+ self._known_directories = []
+
+ def get_basedir(self):
+ return os.getcwd()
+
+ def set_vault_secrets(self, vault_secrets):
+ self._vault_secrets = vault_secrets
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/path.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/path.py
new file mode 100644
index 00000000..044585fe
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/path.py
@@ -0,0 +1,8 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible_collections.cisco.aci.tests.unit.compat.mock import MagicMock
+from ansible.utils.path import unfrackpath
+
+
+mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x)
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/procenv.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/procenv.py
new file mode 100644
index 00000000..f5a5891f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/procenv.py
@@ -0,0 +1,90 @@
+# (c) 2016, Matt Davis <mdavis@ansible.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import sys
+import json
+
+from contextlib import contextmanager
+from io import BytesIO, StringIO
+from ansible_collections.cisco.aci.tests.unit.compat import unittest
+from ansible.module_utils.six import PY3
+from ansible.module_utils._text import to_bytes
+
+
+@contextmanager
+def swap_stdin_and_argv(stdin_data='', argv_data=tuple()):
+ """
+ context manager that temporarily masks the test runner's values for stdin and argv
+ """
+ real_stdin = sys.stdin
+ real_argv = sys.argv
+
+ if PY3:
+ fake_stream = StringIO(stdin_data)
+ fake_stream.buffer = BytesIO(to_bytes(stdin_data))
+ else:
+ fake_stream = BytesIO(to_bytes(stdin_data))
+
+ try:
+ sys.stdin = fake_stream
+ sys.argv = argv_data
+
+ yield
+ finally:
+ sys.stdin = real_stdin
+ sys.argv = real_argv
+
+
+@contextmanager
+def swap_stdout():
+ """
+ context manager that temporarily replaces stdout for tests that need to verify output
+ """
+ old_stdout = sys.stdout
+
+ if PY3:
+ fake_stream = StringIO()
+ else:
+ fake_stream = BytesIO()
+
+ try:
+ sys.stdout = fake_stream
+
+ yield fake_stream
+ finally:
+ sys.stdout = old_stdout
+
+
+class ModuleTestCase(unittest.TestCase):
+ def setUp(self, module_args=None):
+ if module_args is None:
+ module_args = {'_ansible_remote_tmp': '/tmp', '_ansible_keep_remote_files': False}
+
+ args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args))
+
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap = swap_stdin_and_argv(stdin_data=args)
+ self.stdin_swap.__enter__()
+
+ def tearDown(self):
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap.__exit__(None, None, None)
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/vault_helper.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/vault_helper.py
new file mode 100644
index 00000000..dcce9c78
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/vault_helper.py
@@ -0,0 +1,39 @@
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible.module_utils._text import to_bytes
+
+from ansible.parsing.vault import VaultSecret
+
+
+class TextVaultSecret(VaultSecret):
+ '''A secret piece of text. ie, a password. Tracks text encoding.
+
+ The text encoding of the text may not be the default text encoding so
+ we keep track of the encoding so we encode it to the same bytes.'''
+
+ def __init__(self, text, encoding=None, errors=None, _bytes=None):
+ super(TextVaultSecret, self).__init__()
+ self.text = text
+ self.encoding = encoding or 'utf-8'
+ self._bytes = _bytes
+ self.errors = errors or 'strict'
+
+ @property
+ def bytes(self):
+ '''The text encoded with encoding, unless we specifically set _bytes.'''
+ return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors)
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/yaml_helper.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/yaml_helper.py
new file mode 100644
index 00000000..1ef17215
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/mock/yaml_helper.py
@@ -0,0 +1,124 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import io
+import yaml
+
+from ansible.module_utils.six import PY3
+from ansible.parsing.yaml.loader import AnsibleLoader
+from ansible.parsing.yaml.dumper import AnsibleDumper
+
+
+class YamlTestUtils(object):
+ """Mixin class to combine with a unittest.TestCase subclass."""
+ def _loader(self, stream):
+ """Vault related tests will want to override this.
+
+ Vault cases should setup a AnsibleLoader that has the vault password."""
+ return AnsibleLoader(stream)
+
+ def _dump_stream(self, obj, stream, dumper=None):
+ """Dump to a py2-unicode or py3-string stream."""
+ if PY3:
+ return yaml.dump(obj, stream, Dumper=dumper)
+ else:
+ return yaml.dump(obj, stream, Dumper=dumper, encoding=None)
+
+ def _dump_string(self, obj, dumper=None):
+ """Dump to a py2-unicode or py3-string"""
+ if PY3:
+ return yaml.dump(obj, Dumper=dumper)
+ else:
+ return yaml.dump(obj, Dumper=dumper, encoding=None)
+
+ def _dump_load_cycle(self, obj):
+ # Each pass though a dump or load revs the 'generation'
+ # obj to yaml string
+ string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper)
+
+ # wrap a stream/file like StringIO around that yaml
+ stream_from_object_dump = io.StringIO(string_from_object_dump)
+ loader = self._loader(stream_from_object_dump)
+ # load the yaml stream to create a new instance of the object (gen 2)
+ obj_2 = loader.get_data()
+
+ # dump the gen 2 objects directory to strings
+ string_from_object_dump_2 = self._dump_string(obj_2,
+ dumper=AnsibleDumper)
+
+ # The gen 1 and gen 2 yaml strings
+ self.assertEqual(string_from_object_dump, string_from_object_dump_2)
+ # the gen 1 (orig) and gen 2 py object
+ self.assertEqual(obj, obj_2)
+
+ # again! gen 3... load strings into py objects
+ stream_3 = io.StringIO(string_from_object_dump_2)
+ loader_3 = self._loader(stream_3)
+ obj_3 = loader_3.get_data()
+
+ string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper)
+
+ self.assertEqual(obj, obj_3)
+ # should be transitive, but...
+ self.assertEqual(obj_2, obj_3)
+ self.assertEqual(string_from_object_dump, string_from_object_dump_3)
+
+ def _old_dump_load_cycle(self, obj):
+ '''Dump the passed in object to yaml, load it back up, dump again, compare.'''
+ stream = io.StringIO()
+
+ yaml_string = self._dump_string(obj, dumper=AnsibleDumper)
+ self._dump_stream(obj, stream, dumper=AnsibleDumper)
+
+ yaml_string_from_stream = stream.getvalue()
+
+ # reset stream
+ stream.seek(0)
+
+ loader = self._loader(stream)
+ # loader = AnsibleLoader(stream, vault_password=self.vault_password)
+ obj_from_stream = loader.get_data()
+
+ stream_from_string = io.StringIO(yaml_string)
+ loader2 = self._loader(stream_from_string)
+ # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password)
+ obj_from_string = loader2.get_data()
+
+ stream_obj_from_stream = io.StringIO()
+ stream_obj_from_string = io.StringIO()
+
+ if PY3:
+ yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper)
+ yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper)
+ else:
+ yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper, encoding=None)
+ yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper, encoding=None)
+
+ yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue()
+ yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue()
+
+ stream_obj_from_stream.seek(0)
+ stream_obj_from_string.seek(0)
+
+ if PY3:
+ yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper)
+ yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper)
+ else:
+ yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper, encoding=None)
+ yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper, encoding=None)
+
+ assert yaml_string == yaml_string_obj_from_stream
+ assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+ assert (yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string == yaml_string_stream_obj_from_stream ==
+ yaml_string_stream_obj_from_string)
+ assert obj == obj_from_stream
+ assert obj == obj_from_string
+ assert obj == yaml_string_obj_from_stream
+ assert obj == yaml_string_obj_from_string
+ assert obj == obj_from_stream == obj_from_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+ return {'obj': obj,
+ 'yaml_string': yaml_string,
+ 'yaml_string_from_stream': yaml_string_from_stream,
+ 'obj_from_stream': obj_from_stream,
+ 'obj_from_string': obj_from_string,
+ 'yaml_string_obj_from_string': yaml_string_obj_from_string}
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/conftest.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/conftest.py
new file mode 100644
index 00000000..fd6c443d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/conftest.py
@@ -0,0 +1,74 @@
+# Copyright (c) 2017 Ansible Project
+# GNU General Public License v3.0+
+# see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+import sys
+from io import BytesIO
+
+import pytest
+
+import ansible.module_utils.basic
+from ansible.module_utils.six import PY3, string_types
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils.common._collections_compat import MutableMapping
+
+
+@pytest.fixture
+def stdin(mocker, request):
+ old_args = ansible.module_utils.basic._ANSIBLE_ARGS
+ ansible.module_utils.basic._ANSIBLE_ARGS = None
+ old_argv = sys.argv
+ sys.argv = ['ansible_unittest']
+
+ if isinstance(request.param, string_types):
+ args = request.param
+ elif isinstance(request.param, MutableMapping):
+ if 'ANSIBLE_MODULE_ARGS' not in request.param:
+ request.param = {'ANSIBLE_MODULE_ARGS': request.param}
+ if '_ansible_remote_tmp' not in request.param['ANSIBLE_MODULE_ARGS']:
+ request.param['ANSIBLE_MODULE_ARGS']['_ansible_remote_tmp'] = '/tmp'
+ if '_ansible_keep_remote_files' not in request.param['ANSIBLE_MODULE_ARGS']:
+ request.param['ANSIBLE_MODULE_ARGS']['_ansible_keep_remote_files'] = False
+ args = json.dumps(request.param)
+ else:
+ raise Exception('Malformed data to the stdin pytest fixture')
+
+ fake_stdin = BytesIO(to_bytes(args, errors='surrogate_or_strict'))
+ if PY3:
+ mocker.patch('ansible.module_utils.basic.sys.stdin',
+ mocker.MagicMock())
+ mocker.patch('ansible.module_utils.basic.sys.stdin.buffer', fake_stdin)
+ else:
+ mocker.patch('ansible.module_utils.basic.sys.stdin', fake_stdin)
+
+ yield fake_stdin
+
+ ansible.module_utils.basic._ANSIBLE_ARGS = old_args
+ sys.argv = old_argv
+
+
+@pytest.fixture
+def am(stdin, request):
+ old_args = ansible.module_utils.basic._ANSIBLE_ARGS
+ ansible.module_utils.basic._ANSIBLE_ARGS = None
+ old_argv = sys.argv
+ sys.argv = ['ansible_unittest']
+
+ argspec = {}
+ if hasattr(request, 'param'):
+ if isinstance(request.param, dict):
+ argspec = request.param
+
+ am = ansible.module_utils.basic.AnsibleModule(
+ argument_spec=argspec,
+ )
+ am._name = 'ansible_unittest'
+
+ yield am
+
+ ansible.module_utils.basic._ANSIBLE_ARGS = old_args
+ sys.argv = old_argv
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py
new file mode 100644
index 00000000..dd181115
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/module_utils/test_aci.py
@@ -0,0 +1,386 @@
+# -*- coding: utf-8 -*-
+
+# 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
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import sys
+
+from ansible_collections.cisco.aci.tests.unit.compat import unittest
+from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule
+from ansible.module_utils.six import PY2
+from ansible.module_utils._text import to_native
+
+import pytest
+
+
+class AltModule():
+ params = dict(
+ hostname='dummy',
+ port=123,
+ protocol='https',
+ state='present',
+ )
+
+
+class AltACIModule(ACIModule):
+ def __init__(self):
+ self.result = dict(changed=False)
+ self.module = AltModule
+ self.params = self.module.params
+
+
+aci = AltACIModule()
+
+
+try:
+ from lxml import etree
+ if sys.version_info >= (2, 7):
+ from xmljson import cobra
+except ImportError:
+ pytestmark = pytest.mark.skip(
+ "ACI Ansible modules require the lxml and xmljson Python libraries"
+ )
+
+
+class AciRest(unittest.TestCase):
+
+ def test_invalid_aci_login(self):
+ self.maxDiff = None
+
+ error = dict(
+ code='401',
+ text=(
+ 'Username or password is incorrect - '
+ 'FAILED local authentication'
+ ),
+ )
+
+ imdata = [{
+ 'error': {
+ 'attributes': {
+ 'code': '401',
+ 'text': (
+ 'Username or password is incorrect - '
+ 'FAILED local authentication'
+ ),
+ },
+ },
+ }]
+
+ totalCount = 1
+
+ json_response = '{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"Username or password is incorrect - FAILED local authentication"}}}]}' # NOQA
+ aci.response_json(json_response)
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.imdata, imdata)
+ self.assertEqual(aci.totalCount, totalCount)
+
+ # Python 2.7+ is needed for xmljson
+ if sys.version_info < (2, 7):
+ return
+
+ xml_response = '''<?xml version="1.0" encoding="UTF-8"?>
+ <imdata totalCount="1">
+ <error
+ code="401"
+ text="Username or password is incorrect - FAILED local
+authentication"
+ />
+ </imdata>
+ '''
+ aci.response_xml(xml_response)
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.imdata, imdata)
+ self.assertEqual(aci.totalCount, totalCount)
+
+ def test_valid_aci_login(self):
+ self.maxDiff = None
+
+ imdata = [{
+ 'aaaLogin': {
+ 'attributes': {
+ 'token': 'ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem', # NOQA
+ 'siteFingerprint': 'NdxD72K/uXaUK0wn',
+ 'refreshTimeoutSeconds': '600',
+ 'maximumLifetimeSeconds': '86400',
+ 'guiIdleTimeoutSeconds': '1200',
+ 'restTimeoutSeconds': '90',
+ 'creationTime': '1500134817',
+ 'firstLoginTime': '1500134817',
+ 'userName': 'admin',
+ 'remoteUser': 'false',
+ 'unixUserId': '15374',
+ 'sessionId': 'o7hObsqNTfCmDGcZI5c4ng==',
+ 'lastName': '',
+ 'firstName': '',
+ 'version': '2.0(2f)',
+ 'buildTime': 'Sat Aug 20 23:07:07 PDT 2016',
+ 'node': 'topology/pod-1/node-1',
+ },
+ 'children': [{
+ 'aaaUserDomain': {
+ 'attributes': {
+ 'name': 'all',
+ 'rolesR': 'admin',
+ 'rolesW': 'admin',
+ },
+ 'children': [{
+ 'aaaReadRoles': {
+ 'attributes': {},
+ },
+ }, {
+ 'aaaWriteRoles': {
+ 'attributes': {},
+ 'children': [{
+ 'role': {
+ 'attributes': {
+ 'name': 'admin',
+ },
+ },
+ }],
+ },
+ }],
+ },
+ }, {
+ 'DnDomainMapEntry': {
+ 'attributes': {
+ 'dn': 'uni/tn-common',
+ 'readPrivileges': 'admin',
+ 'writePrivileges': 'admin',
+ },
+ },
+ }, {
+ 'DnDomainMapEntry': {
+ 'attributes': {
+ 'dn': 'uni/tn-infra',
+ 'readPrivileges': 'admin',
+ 'writePrivileges': 'admin',
+ },
+ },
+ }, {
+ 'DnDomainMapEntry': {
+ 'attributes': {
+ 'dn': 'uni/tn-mgmt',
+ 'readPrivileges': 'admin',
+ 'writePrivileges': 'admin',
+ },
+ },
+ }],
+ },
+ }]
+
+ totalCount = 1
+
+ json_response = '{"totalCount":"1","imdata":[{"aaaLogin":{"attributes":{"token":"ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem","siteFingerprint":"NdxD72K/uXaUK0wn","refreshTimeoutSeconds":"600","maximumLifetimeSeconds":"86400","guiIdleTimeoutSeconds":"1200","restTimeoutSeconds":"90","creationTime":"1500134817","firstLoginTime":"1500134817","userName":"admin","remoteUser":"false","unixUserId":"15374","sessionId":"o7hObsqNTfCmDGcZI5c4ng==","lastName":"","firstName":"","version":"2.0(2f)","buildTime":"Sat Aug 20 23:07:07 PDT 2016","node":"topology/pod-1/node-1"},"children":[{"aaaUserDomain":{"attributes":{"name":"all","rolesR":"admin","rolesW":"admin"},"children":[{"aaaReadRoles":{"attributes":{}}},{"aaaWriteRoles":{"attributes":{},"children":[{"role":{"attributes":{"name":"admin"}}}]}}]}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-common","readPrivileges":"admin","writePrivileges":"admin"}}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-infra","readPrivileges":"admin","writePrivileges":"admin"}}},{"DnDomainMapEntry":{"attributes":{"dn":"uni/tn-mgmt","readPrivileges":"admin","writePrivileges":"admin"}}}]}}]}' # NOQA
+ aci.response_json(json_response)
+ self.assertEqual(aci.imdata, imdata)
+ self.assertEqual(aci.totalCount, totalCount)
+
+ # Python 2.7+ is needed for xmljson
+ if sys.version_info < (2, 7):
+ return
+
+ xml_response = '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1">\n<aaaLogin token="ZldYAsoO9d0FfAQM8xaEVWvQPSOYwpnqzhwpIC1r4MaToknJjlIuAt9+TvXqrZ8lWYIGPj6VnZkWiS8nJfaiaX/AyrdD35jsSxiP3zydh+849xym7ALCw/fFNsc7b5ik1HaMuSUtdrN8fmCEUy7Pq/QNpGEqkE8m7HaxAuHpmvXgtdW1bA+KKJu2zY1c/tem" siteFingerprint="NdxD72K/uXaUK0wn" refreshTimeoutSeconds="600" maximumLifetimeSeconds="86400" guiIdleTimeoutSeconds="1200" restTimeoutSeconds="90" creationTime="1500134817" firstLoginTime="1500134817" userName="admin" remoteUser="false" unixUserId="15374" sessionId="o7hObsqNTfCmDGcZI5c4ng==" lastName="" firstName="" version="2.0(2f)" buildTime="Sat Aug 20 23:07:07 PDT 2016" node="topology/pod-1/node-1">\n<aaaUserDomain name="all" rolesR="admin" rolesW="admin">\n<aaaReadRoles/>\n<aaaWriteRoles>\n<role name="admin"/>\n</aaaWriteRoles>\n</aaaUserDomain>\n<DnDomainMapEntry dn="uni/tn-common" readPrivileges="admin" writePrivileges="admin"/>\n<DnDomainMapEntry dn="uni/tn-infra" readPrivileges="admin" writePrivileges="admin"/>\n<DnDomainMapEntry dn="uni/tn-mgmt" readPrivileges="admin" writePrivileges="admin"/>\n</aaaLogin></imdata>\n''' # NOQA
+ aci.response_xml(xml_response)
+ self.assertEqual(aci.imdata, imdata)
+ self.assertEqual(aci.totalCount, totalCount)
+
+ def test_invalid_input(self):
+ self.maxDiff = None
+
+ error = dict(
+ code='401',
+ text=(
+ 'Username or password is incorrect - '
+ 'FAILED local authentication'
+ ),
+ )
+
+ imdata = [{
+ 'error': {
+ 'attributes': {
+ 'code': '401',
+ 'text': (
+ 'Username or password is incorrect - '
+ 'FAILED local authentication'
+ ),
+ },
+ },
+ }]
+
+ totalCount = 1
+
+ json_response = '{"totalCount":"1","imdata":[{"error":{"attributes":{"code":"401","text":"Username or password is incorrect - FAILED local authentication"}}}]}' # NOQA
+ aci.response_json(json_response)
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.imdata, imdata)
+ self.assertEqual(aci.totalCount, totalCount)
+
+ # Python 2.7+ is needed for xmljson
+ if sys.version_info < (2, 7):
+ return
+
+ xml_response = '''<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1">
+ <error
+ code="401"
+ text="Username or password is incorrect - FAILED local
+authentication"
+ />
+ </imdata>
+ '''
+ aci.response_xml(xml_response)
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.imdata, imdata)
+ self.assertEqual(aci.totalCount, totalCount)
+
+ def test_empty_response(self):
+ self.maxDiffi = None
+
+ if PY2:
+ error_text = (
+ "Unable to parse output as JSON, see 'raw' output. "
+ "No JSON object could be decoded"
+ )
+ else:
+ error_text = (
+ "Unable to parse output as JSON, see 'raw' output. "
+ "Expecting value: line 1 column 1 (char 0)"
+ )
+
+ error = dict(
+ code=-1,
+ text=error_text,
+ )
+ raw = ''
+
+ json_response = ''
+ aci.response_json(json_response)
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.result['raw'], raw)
+
+ # Python 2.7+ is needed for xmljson
+ if sys.version_info < (2, 7):
+ return
+
+ elif etree.LXML_VERSION < (3, 3, 0, 0):
+ error_text = (
+ "Unable to parse output as XML, see 'raw' output. "
+ "None"
+ ),
+ elif etree.LXML_VERSION < (4, 0, 0, 0):
+ error_text = to_native(
+ (
+ u"Unable to parse output as XML, see 'raw' output. "
+ u"None (line 0)"
+ ),
+ errors='surrogate_or_strict'
+ )
+ elif PY2:
+ error_text = (
+ "Unable to parse output as XML, see 'raw' output. "
+ "Document is empty, line 1, column 1 (line 1)"
+ )
+ else:
+ error_text = None
+
+ xml_response = ''
+ aci.response_xml(xml_response)
+
+ if error_text is None:
+ # errors vary on Python 3.8+ for unknown reasons
+ # accept any of the following error messages
+ errors = (
+ (
+ "Unable to parse output as XML, see 'raw' output. "
+ "None (line 0)"
+ ),
+ (
+ "Unable to parse output as XML, see 'raw' output. "
+ "Document is empty, line 1, column 1 (<string>, line 1)"
+ ),
+ )
+
+ for error in errors:
+ if error in aci.error['text']:
+ error_text = error
+ break
+
+ error = dict(
+ code=-1,
+ text=error_text,
+ )
+
+ raw = ''
+
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.result['raw'], raw)
+
+ def test_invalid_response(self):
+ self.maxDiff = None
+
+ if sys.version_info < (2, 7):
+ error_text = (
+ "Unable to parse output as JSON, see 'raw' output."
+ " Expecting object: line 1 column 8 (char 8)"
+ )
+ elif PY2:
+ error_text = (
+ "Unable to parse output as JSON, see 'raw' output."
+ " No JSON object could be decoded"
+ )
+ else:
+ error_text = (
+ "Unable to parse output as JSON, see 'raw' output."
+ " Expecting value: line 1 column 9 (char 8)"
+ )
+
+ error = dict(
+ code=-1,
+ text=error_text,
+ )
+
+ raw = '{ "aaa":'
+
+ json_response = '{ "aaa":'
+ aci.response_json(json_response)
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.result['raw'], raw)
+
+ # Python 2.7+ is needed for xmljson
+ if sys.version_info < (2, 7):
+ return
+
+ elif etree.LXML_VERSION < (3, 3, 0, 0):
+ error_text = (
+ "Unable to parse output as XML, see 'raw' output. "
+ "Couldn't find end of Start Tag aaa line 1, line 1, column 5"
+ )
+ elif PY2:
+ error_text = (
+ "Unable to parse output as XML, see 'raw' output. "
+ "Couldn't find end of Start Tag aaa line 1, line 1, column 6 "
+ "(line 1)"
+ )
+
+ else:
+ error_text = (
+ "Unable to parse output as XML, see 'raw' output. "
+ "Couldn't find end of Start Tag aaa line 1, line 1, column 6 "
+ "(<string>, line 1)"
+ )
+
+ error = dict(
+ code=-1,
+ text=error_text,
+ )
+
+ raw = '<aaa '
+
+ xml_response = '<aaa '
+ aci.response_xml(xml_response)
+ self.assertEqual(aci.error, error)
+ self.assertEqual(aci.result['raw'], raw)
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/__init__.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/utils.py b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/utils.py
new file mode 100644
index 00000000..c692792f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/modules/utils.py
@@ -0,0 +1,52 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+
+from ansible_collections.cisco.aci.tests.unit.compat import unittest
+from ansible_collections.cisco.aci.tests.unit.compat.mock import patch
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+
+
+def set_module_args(args):
+ if '_ansible_remote_tmp' not in args:
+ args['_ansible_remote_tmp'] = '/tmp'
+ if '_ansible_keep_remote_files' not in args:
+ args['_ansible_keep_remote_files'] = False
+
+ args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
+ basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+class AnsibleExitJson(Exception):
+ pass
+
+
+class AnsibleFailJson(Exception):
+ pass
+
+
+def exit_json(*args, **kwargs):
+ if 'changed' not in kwargs:
+ kwargs['changed'] = False
+ raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+ kwargs['failed'] = True
+ raise AnsibleFailJson(kwargs)
+
+
+class ModuleTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_module = patch.multiple(basic.AnsibleModule,
+ exit_json=exit_json,
+ fail_json=fail_json)
+ self.mock_module.start()
+ self.mock_sleep = patch('time.sleep')
+ self.mock_sleep.start()
+ set_module_args({})
+ self.addCleanup(self.mock_module.stop)
+ self.addCleanup(self.mock_sleep.stop)
diff --git a/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/requirements.txt b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/requirements.txt
new file mode 100644
index 00000000..c27ba892
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/aci/tests/unit/requirements.txt
@@ -0,0 +1,10 @@
+requests
+setuptools > 0.6 # pytest-xdist installed via requirements does not work with very old setuptools (sanity_ok)
+unittest2 ; python_version < '2.7'
+importlib ; python_version < '2.7'
+netaddr
+ipaddress
+
+# requirement for aci_rest module
+xmljson
+lxml \ No newline at end of file